How to Form-encode a dictionary in Python? - python

I am interacting with a REST API and need to explicitly form-encode the request body before sending.
The urllib module has a urlencode method, but I see no equivalent for form-encode, presumably as dictionaries are automatically encoded when using urllib to POST the request.
Is there a built in method that I can use to form-encode an object? For example:
params={'f':'json','type':'map'}
post_body = formencode(params)
Producing post_body:
f=json
type=map
In this instance I'm using WinHttpRequest through the win32com module as it can take care of authentication natively so I don't need to handle credentials in the script.

Related

How can I get Custom Payload as string

I have a Dialogflow CX agent that returns a Custom payload. My client is a Python application using the dialogflowcx_v3beta1 SDK to call DetectIntent. The application needs to forward the custom payload in JSON format to another application, but I have been unable to find a way to convert the structured payload to JSON. There is no schema associated with the custom payload, which could be literally any valid JSON, and because it will simply be forwarded to another component, the application has no reason to interpret the content in any way.
Is there a way to serialize the custom payload to JSON?
Unless you're asking a Python question, the "CX Solution" could be to use the Fulfillment text instead of the Custom Payload feature, and include there the serialized JSON.

How to perform Tornado requests within a Tornado request

I am using the Tornado Web Server (version 4.1) with Python 2.7 to create a REST web application. One of my request handlers (web.RequestHandler) handles batch requests consisting of multiple HTTP requests combined into one HTTP request using the multipart/mixed content type. I currently have the batch request handler able to receive the POST request and parse the multipart/mixed content into individual requests that look like this:
GET /contacts/3 HTTP/1.1
Accept: application/json
My question is, what would be a good way of converting these inner batched requests into requests that Tornado can service from within my request handler? I would like to collect the responses within my batch request handler and, once these requests are all complete, return a single multipart/mixed response containing all the batched responses.
Using an HTTPClient to execute the batched requests feels like overkill. It seems like I should be able to build a request object and inject it into the web.Application for processing--I'm at a loss as to how to do this however. Thanks!
Tornado doesn't have any direct support for this. Going through an HTTP client is probably going to be the simplest solution. However, if you're really interested in avoiding that route, here's a sketch of a solution, which relies on the interfaces defined in the tornado.httputil module.
Define a class that implements the HTTPConnection interface by saving the arguments to write and write_headers into internal buffers.
The Application is an HTTPServerConnectionDelegate. Call its start_request method with an instance of your connection class as both arguments (the first argument doesn't really matter, but it should be unique and since we won't be reusing "connections" that object is fine).
start_request returns an HTTPMessageDelegate. Call its headers_received, data_received (for POST/PUT), and finish methods to make your request. Once you have called finish, the handler will run and make calls back into your connection object.

POST parameters formatted as JSON

I am writing a web service using Django that will be consumed from a MS SharePoint workflow. In the SP workflow, I created a dictionary with 2 items (id:1, text:'foo'), and used this dictionary as the request content. However, instead of using the dictionary to format a traditional POST parameter list, it sends it as a JSON object in the body of the POST request, so instead of the expected:
id=1&text=foo
in the body of the request, there is this:
{"id":1,"text":"foo"}
which of course, in turn, does not get parsed correctly by Python/Django (I am not sure who exactly does the parsing). How can I either get it to parse JSON, or get SharePoint to send traditionally encoded POST parameters?
EDIT
I saw other posts that explain how to get the raw body and parse the JSON. I was looking for a solution that would either:
Make SharePoint send normal data, or
Get Django to respect the Content-type header that states the data is JSON
There is no need for any parsing at the framework level. The body of the post request is always available in request.body, so you can access it directly:
result = json.loads(request.body)
May be it will help you bit more to handle.
import json
import urlparse
json.dumps(urlparse.parse_qs("id=1&text=foo"))

How to customize error response in a Turbogears2 controller

I'm using Turbogears2 to develop a small web application. And in some of my "controllers", I would like to response the client a json object with error information inside instead of an html page follows the standard error page template, because the ajax client can read the error message and have it's own way to display it.
There are multiple ways you can achieve this. If it is only bound to some controller you can easily register a controller wrapper for them (using tg.hooks.wrap_controller) and return JSON instead of plain error when needed. Controller wrappers are documented on http://turbogears.readthedocs.org/en/latest/turbogears/hooks.html#controller-wrappers
Otherwise another options is to use a decorator on the controller function to catch the error. This is what is also done by tgext.crudwhen reporting json errors through the catch_errors custom decorator: https://github.com/TurboGears/tgext.crud/blob/master/tgext/crud/decorators.py#L114
The controller wrapper solution is usually more powerful as it can be applied also to third party controllers. Otherwise you can even hijack the ErrorController in controllers/error.py to return json using json.dumps (TurboGears returns the response as is when it's a string or a tg.Response instance).

Pyramid subrequests

I need to call GET, POST, PUT, etc. requests to another URI because of search, but I cannot find a way to do that internally with pyramid. Is there any way to do it at the moment?
Simply use the existing python libraries for calling other webservers.
On python 2.x, use urllib2, for python 3.x, use urllib.request instead. Alternatively, you could install requests.
Do note that calling external sites from your server while serving a request yourself could mean your visitors end up waiting for a 3rd-party web server that stopped responding. Make sure you set decent time outs.
pyramid uses webob which has a client api as of version 1.2
from webob import Request
r = Request.blank("http://google.com")
response = r.send()
generally anything you want to override for the request you would just pass in as a parameter.
from webob import Request
r = Request.blank("http://facebook.com",method="DELETE")
another handy feature is that you can see the request as the http that is passed over the wire
print r
DELETE HTTP/1.0
Host: facebook.com:80
docs
Also check the response status code: response.status_int
I use it for example, to introspect my internal URIs and see whether or not a given relative URI is really served by the framework (example to generate breadcrumbs and make intermediate paths as links only if there are pages behind)

Categories

Resources