Analyzing post request - c++

I'm trying to make post request using c++ Qt.
The target site is http://www.artlebedev.ru/tools/decoder/advanced/
The site looks so:
I inspected it with browser.
And there is one strange thing for me - random number in header.
So, I'm not sure whether I send data for post request correctly.
What have they done it for?
I make my request so (as browser does):
postdata.append("accept:*/*&");
postdata.append("accept-charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3&");
postdata.append("Accept-Encoding:gzip,deflate,sdch&");
postdata.append("Accept-Language:en-US,en;q=0.8&");
postdata.append("Connection:keep-alive&");
postdata.append("Content-Length:36&");
postdata.append("Content-Type:application/x-www-form-urlencoded&");
postdata.append("Cookie:__utma=1.904416008.1352897318.1352905816.1352909441.3; __utmc=1; __utmz=1.1352897318.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); __atuvc=7%7C46&");
postdata.append("Host:www.artlebedev.ru&");
postdata.append("Origin:http://www.artlebedev.ru&");
postdata.append("Referer:http://www.artlebedev.ru/tools/decoder/advanced/&");
postdata.append("User-Agent:Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11&");
postdata.append("X-Requested-With:XMLHttpRequest&");
postdata.append("random:0.9632773566991091&"); // I have no idea about this number
postdata.append("Form Dataview URL encoded&");
postdata.append("csin:0&");
postdata.append("csout:0&");
postdata.append("text:fvddas&");
postdata.append("Decode:go");
I get webpage in answer. But that webpage doesn't contain decoded string. Only empty stings. It looks so:
This is my first attempt to make post request, please help me find a way out.

The random value looks like some kind of Cross-site request forgery token to prevent people from doing what you are trying to do, but it is actually not being used. If I re-issue the request using Fiddler without any cookies or the random value, the request still succeeds.
In fact, this request also does:
POST http://www.artlebedev.ru/tools/decoder/advanced/ HTTP/1.1
Host: www.artlebedev.ru
Content-Type: application/x-www-form-urlencoded
Content-Length: 33
csin=0&csout=0&text=foo&Decode=go
So there must be something wrong with your request, and I guess you shouldn't have just copypasted the request from an external viewer into code, but looked at what you are doing:
postdata.append("Form Dataview URL encoded&");
This is not an HTTP header. It's even nice of the server to not respond with a 400 Bad Request. What should be in the place of that line is a single CRLF, to separate the headers from the entity ('request body').
It could prove useful if you output the contents of postdata just before you send it, to look if you can see something wrong.
Perhaps if you like the encoding translation that site can do (or whatever it is it does), you can ask the creators of the site if they have a publicly available API that you can address, or perhaps they'll even share some code or point you towards valuable resources to recreate such a conversion for yourself.

Related

Chilkat http post and respond bodystr 32000 char limitation (ChilkatAx-9.5.0-win32)

I have a problem with the response I get from the soap service.
I set the "SetSslClientCertPfx" with invoke method:
certificate name
password
I set the "SetRequestHeader" with invoke method:
Content-Type
text/xml; charset=UTF-8
I set the "SetRequestHeader" with invoke method:
SOAPAction
urloftheaction
Invoke method "PostXml":
Server link
blob with file content
utf-8
I check for errors with "get.LastErrorText"
I get the response with "get.bodyStr"
For the result, I have a char(32000) field. I tried increasing this to 64000 characters but that way I get an empty result. I also tried to replace the char field with the blob. That also didn't work. It's like the method itself is limited to 32000 chars.
I read that for large results I should use "LastStringResult" but it only works for MySQL. Is there a solution to my problem?
I'm assuming the content returned in the body of the HTTP response is XML? (or perhaps JSON?) In either case, the best thing to do is to avoid getting the returned content as a string. Let me explain...
For example, instead of calling response.GetBodyStr(), call response.GetBodyXml(xmlObj) (see https://www.chilkatsoft.com/refdoc/xChilkatHttpResponseRef.html#method4 )
The GetBodyXml method loads the response body into the XML object passed in the argument. Then your application can work with the contents of the XML via the Chilkat XML API, i.e parsing out the various parts as needed.

Using HTTP URIs as identifiers of resources in RESTful web API

Usually to retrieve a resource one uses:
GET http://ws.mydomain.com/resource/123212
But what if your item IDs are HTTP URIs?:
GET http://ws.mydomain.com/resource/http://id.someotherdomain.com/SGX.3211
Browsers replace two slashes with one, and the request turns into:
GET http://ws.mydomain.com/resource/http:/id.someotherdomain.com/SGX.3211
which will not work.
URI encoding the "http://id.someotherdomain.com/SGX.3211" -part results in HTTP 400 - Bad request.
Is there a best practice for handling this?
Edit:
Then of course if we would need to have (I don't at the moment) request in form:
resources/ID/collections/ID
and all IDs are HTTP URIs, things get out of hand... Possibly one could do something like this and parse the contents inside the curly braces:
resources/{http://id...}/collections/{http://id...}
Encode the other system's URI, and then pass the value as a query parameter:
GET http://ws.mydomain.com/resource?ref=http%3A%2F%2Fid.someotherdomain.com%2FSGX.3211
Ugly looking, but no one said that URIs used in a REST architecture have to be beautiful. :)
By the way, a GET actually looks like this when it's sent:
GET /resource?ref=http%3A%2F%2Fid.someotherdomain.com%2FSGX.3211 HTTP/1.1
Host: ws.mydomain.com
UPDATE: apparently you no longer have to encode "/" and "?" within a query component. From RFC 3986:
The characters slash ("/") and question mark ("?") may represent data
within the query component. Beware that some older, erroneous
implementations may not handle such data correctly when it is used as
the base URI for relative references (Section 5.1), apparently
because they fail to distinguish query data from path data when
looking for hierarchical separators. However, as query components are
often used to carry identifying information in the form of "key=value"
pairs and one frequently used value is a reference to another URI, it
is sometimes better for usability to avoid percent-encoding those
characters.
So you could legally do this:
GET /resource?ref=id.someotherdomain.com/SGX.3211 HTTP/1.1
Host: ws.mydomain.com

Zero-length URL Segments

Using the latest versions of Flask and Flask-RESTful, I have some very basic routes defined as such:
def build_uri_rules(uri_map):
for cls, uri in uri_map.iteritems():
api.add_resource(cls, uri)
uris = {
SampleController: '/samples/<string:hash_or_id>',
SampleFamilyController: '/samples/<string:hash_or_id>/family',
}
build_uri_rules(uris)
This works for uris requested 'properly', but what if the /samples/ endpoint is hit without a parameter, or the sample*family endpoint is hit with an empty sample id? Currently, this results in a 404 error. This works well enough, but I believe the proper thing here would be to throw a 400 error, as they found a proper URL but their data is improperly structured. Is there a way that I can force this behavior?
As a side note:
Looking through the Werkzeug docs, I see that werkzeug.routing allows a minimum length for certain url parameters, but I also see that it's got a minimum of 1. Admittedly, I've not look for why this is the case, but would this be the right tree to bark up? or should I rather simply create a global 404 handler that checks for the length of the parameter and raise the proper error from there?
Thanks!
EDITED: For code correctness.
I would say that hitting /samples/ or /samples/family (or even /samples//family) should result in a 404 as there is nothing at that endpoint.
If, however, you want to do otherwise, the simplest way to handle it would be create a 404 handler for just /samples/ and /samples/family that returns a note with more information about what the consumers of your API are most likely doing wrong.
uris = {
Explanitory400Controller: '/samples/',
SampleController: '/samples/<string:hash_or_id>',
Explanitory400Controller: '/samples/family',
SampleFamilyController: '/samples/<string:hash_or_id>/family',
}

REST: Mapping application errors to HTTP Status codes

Is it to be considered good practice to reuse RFC HTTP Status codes like this, or should we be making up new ones that map exactly to our specific error reasons?
We're designing a web service API around a couple of legacy applications.
In addition to JSON/XML data structures in the Response Body, we aim to return HTTP Status Codes that make sense to web caches and developers.
But how do you go about mapping different classes of errors onto appropriate HTTP Status codes? Everyone on the team agrees on the following:
GET /package/1234 returns 404 Not Found if 1234 doesn't exist
GET /package/1234/next_checkpoint returns 400 Bad Request if "next_checkpoint" and 1234 are valid to ask for but next_checkpont here doesn't make sense...
and so on... but, in some cases, things needs to be more specific than just "400" - for example:
POST /dispatch/?for_package=1234 returns 412 Precondition Failed if /dispatch and package 1234 both exist, BUT 1234 isn't ready for dispatch just yet.
(Edit: Status codes in HTTP/1.1 and Status codes in WebDAV ext.)
RESTful use of HTTP means that you must keep the API uniform. This means that you cannot add domain specific methods (ala GET_STOCK_QUOTE) but it also means that you cannot add domain specific error codes (ala 499 Product Out Of Stock).
In fact, the HTTP client error codes are a good design check because if you design your resource semantics properly, the HTTP error code meanings will correctly express any errors. If you feel you need additional error codes, your resource design is likely wrong.
Jan
422 Unprocessable Entity is a useful error code for scenarios like this. See this question what http response code for rest service on put method when domain rules invalid for additional information.
GET /package/1234/next_checkpoint
returns 400 Bad Request if
"next_checkpoint" and 1234 are valid
to ask for but next_checkpont here
doesn't make sense...
This is the wrong way to think about that URI.
URIs are opaque, so observing that parts of it are 'valid' and others are not doesn't make any sense from a client perspective. Therefore you should 'just' return a 404 to the client, since the resource "package/1234/next_checkpoint" doesn't exist.
You should use 4xx series responses that best match your request when the client makes a mistake, though be careful to not use ones that are meant for specific headers or conditions. I tend to return a human-readable status message and either a plain-text version of the error as the response body or a structured error message, depending on application context.
Update: Upon further reading of the RFC, "procondition failed" is meant for the conditional headers, such as "if-none-match". I'd give a general 400 message for that instead.
Actually, you shouldn't do this at all. Your use of 404 Not Found is correct, but 400 Bad Request is being used improperly. A 400 Bad Request according to the RFC is used solely when the HTTP protocol is malformed. In your case, the request is syntactically correct, it is just an unexpected argument. You should return a 500 Server Error and then include an error code in your REST result.

Best practice for handling HTTP HEAD request with Django on App Engine

I'm receiving HEAD requests in my application, and wondering on the best way to handle them. Options are:
convert them to GETs, process GET normally, then:
strip the body (though I'm not sure how - response.content = '' doesn't seem to do it.
it seems app engine auto-strips the body, giving a warning "Dropping unexpected body in response to HEAD request"
It seems this is clean, and can be written nicely using decorators or middleware.
Handle each HEAD request specially:
this means I could avoid a DataStore access in some (many?) cases.
There is a risk, apparently, that middleware which sets the Content-length header will be prevented from doing so by this approach.
Anything else? Which should I do? Does using App Engine make a difference here? Are there subtle details; if so, is there appropriate middleware to use? To convert to GET, is `request.method = "GET" sufficient (it seems to work)?
Did you intend for you application to handle HEAD requests, or are these coming from some anonymous source? You certainly aren't obligated to honor a HEAD request. You can just return with a status code of 405 (Method not allowed) and provide the Allow header with GET or whatever you mean to handle.
I don't think that manually setting request.method to GET is meaningful; in all probability, you are just returning a response that is larger than what the requester wanted. They just wanted to see the headers for the response. If you don't want to handle the HEAD, do the 405 and Allow header approach.
Generally, a client sends a HEAD request because they are trying to be smart about not handling a full response if they don't need to. They are checking to see if the Content-Length has changed since the last time that they saw the response, or they want to see the Last-Modified or Expires header.
It is certainly well-behaved for your application to gracefully handle HEAD requests, but you don't have to.