Hi How to handle 302 response in dp:url-open(), and how to deleate all the request http headers before sending to back-end. those headers are dynamic.
Thanks,
Manoj.
For(hypothetically) a Multi-Protocol Gateway, go in the "advanced" tab, switch the "Follow Redirects" option off. Then the 302 http response is treated just as any 2xx responses.
From that point on, you can create a GatewayScript code that test the error code (and if value == 302), then delete all headers.
The code would look something like this (please correct if I missed something):
var hm = require('header-metadata');
var all_Headers = hm.current.headers;
console.error(all_Headers);
if (hm.current.statusCode == 302) {
for (var headerName in all_Headers) {
hm.current.remove(headerName);
}
}
Here are some good references for GatewayScript:
Nice IBM "playground" site, click on "samples" for the cool part
Official GatewayScript code documentation
Specific part about header deleting in GatewayScript
I partially based my example on this healthcheck example
Related
Using the json-rpc-cpp library, I am creating an EOS Wallet using wallet RPC.
HttpClient *temp = new HttpClient("http://127.0.0.1:30031/v1/wallet/create");
string res;
string str = "testwallet1";
temp->SendRPCMessage(str, res);
cout<<"res : "<<res<<endl;
It is creating the wallet successfully, but after that I am getting the following exception.
unknown file: Failure
C++ exception with description "Exception -32603 : INTERNAL_ERROR: : "PW5JcEu7jTXd7XUYLWkPuCUbr1pqBhusqRFfhSVToqUNcDuZ3oeYK"" thrown in the test body.
I found that HttpClient receives a 201 response code. I have no idea how to avoid that exception. Does anyone have any idea?
The issue is caused by a bug in the HttpClient::SendRPCMessage() implementation.
Internally, HttpClient uses libcurl for its HTTP handling, and at the very end of the SendRPCMessage() implementation is the following check if curl_easy_perform() is successful:
long http_code = 0;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
if (http_code != 200) {
throw JsonRpcException(Errors::ERROR_RPC_INTERNAL_ERROR, result);
}
As you can see, SendRPCMessage() throws an exception for ANY HTTP response code other than 200. But per the HTTP standard, ALL 2xx response codes indicate success, not just 200. In this case, response code 201 means:
10.2.2 201 Created
The request has been fulfilled and resulted in a new resource being created. The newly created resource can be referenced by the URI(s) returned in the entity of the response, with the most specific URI for the resource given by a Location header field. The response SHOULD include an entity containing a list of resource characteristics and location(s) from which the user or user agent can choose the one most appropriate. The entity format is specified by the media type given in the Content-Type header field. The origin server MUST create the resource before returning the 201 status code. If the action cannot be carried out immediately, the server SHOULD respond with 202 (Accepted) response instead.
A 201 response MAY contain an ETag response header field indicating the current value of the entity tag for the requested variant just created, see section 14.19.
This is clearly a logic error in the implementation of SendRPCMessage(). The check of the http_code should be more like this instead:
if ((http_code / 100) != 2)
This will treat all 2xx response codes as success.
I have filed a bug report with json-rpc-cpp's author:
#278 HttpClient::SendRPCMessage() throws ERROR_RPC_INTERNAL for successful HTTP responses
201 basically means that your request was processed successfully. As this source explains:
201 CREATED The request has been fulfilled and has resulted in one or more new resources being created.
The primary resource created by the request is identified by either a
Location header field in the response or, if no Location field is
received, by the effective request URI.
The 201 response payload typically describes and links to the
resource(s) created. See Section 7.2 of RFC7231 for a discussion of
the meaning and purpose of validator header fields, such as ETag and
Last-Modified, in a 201 response.
The exception must be thrown when any further processing is applied to the response data.
I can't tell what exactly causes this without more information.
I'm working with a slightly unconventional API that is expecting a JSON body with a GET request and I have no control over this. Unfortunately, every time I attempt to make the request, it seems to completely disappear and never make it to the API. I originally wrote the request using a standard URLSession and then switched to try Alamofire in an attempt to fix it but ended with the same result. My request looks like this:
Alamofire.request("http://192.168.1.1:8000/connect/", method: .get, parameters: ["test": "test"], encoding: JSONEncoding.default)
.responseJSON { response in
let body = response.request?.httpBody
guard response.result.isSuccess else {
onCompletion(nil)
return
}
onCompletion(response.result.value as! [String : Any]?)
}
This exact code works for a different request where there is no JSON in the body, but seemingly the moment I add it, it just times out. This has already been discussed on the alamofire github repo (https://github.com/Alamofire/Alamofire/issues/1819) but the final comment with what should be working code isn't really any different to mine, so doesn't provide any help, nor do the other linked issues.
Printing the request with debugPrint gives me this curl command
$ curl -i \
-H "Content-Type: application/json" \
-d "{\"test\":\"test\"}" \
"http://192.168.1.1:8000/connect/"
Which is missing the -X GET flag, but when I add that in, the request works as expected and the server responds, so I know the API itself is working and is happy processing the JSON in the body, so I'm at a loss as to what's going on.
I've installed Timberjack to attempt to trace things, which didn't give me any more info at all, just what I already knew
Request: GET http://192.168.1.1:8000/connect/
Headers: [
Content-Type : application/json
Content-Length : 24
]
Although I'm not sure if it's supposed to be showing me the body as well which it isn't?
In both cases (URLSession and Alamofire) the request gives the following output which I don't see at any other time:
2017-01-22 23:31:09.797453 my-app[3755:1349066] [] nw_endpoint_flow_service_writes [2 192.168.1.1:8000 ready socket-flow (satisfied)] Write request has 4294967295 frame count, 0 byte count
2017-01-22 23:32:04.484182 my-app[3755:1349066] [] __tcp_connection_write_eof_block_invoke Write close callback received error: [89] Operation canceled
Anyone have any ideas on what's going on as I'm completely at a loss at this point.
Update
I've done some more digging. If I change the endpoint to https://httpbin.org/get then the request goes through just fine and I get a response. Whilst this kind of suggests the API server is refusing to process the request, it's still working with the cURL command so that can't really be the issue.
I also forgot to mention (although not sure it should make a difference) that the API I'm trying to communicate with is connected via an ad-hoc wifi. Other requests to it work just fine though so I can definitely communicate with it.
Update 2
So I've been able to switch the server to using POST instead of GET and unsurprisingly it now works, however I would still love to know of a solution to the original problem
URLSession and CFHTTPMessage cannot send a message body for a GET request. They send the content length for the body, but do not send the body itself. This results in a timeout.
In order to resolve this issue I've used libcurl to handle the GET requests which have a message body to my project. I use URLSession everywhere else. When you add a body to a request using libcurl it changes the request to a POST, but that can be changed back to a GET after setting the body and before submitting the request.
I am struggling what is the best practice for PATCH method.
I see couple of possibilities:
Return HTTP status code 200 OK with updated object.
Return HTTP status code 204 No Content.
What would be the best one?
The specification states:
The 204 response code is used because the response does not carry a
message body (which a response with the 200 code would have). Note
that other success codes could be used as well.
Which just means you may decide to return a body or not, the response codes should then be 200 or 204 respectively. Neither is better or worse than the other. You may find that it is practical to just return the changed content, so the client does not have to make a new request to get the new content.
Note: using the PATCH is quite tricky, as you must define a mime-type for applying change-sets to your resource. This may not be what you want. More often than not, PATCH can be solved by just creating a new resource that should have been a resource anyway.
I'm looking for some perspective. I'm entirely new to API programming. I've found that calling eBay's GeteBayTime method is correctly returning JSON but with a header of text/plain;charset=utf-8, not application/json. Is this an eBay bug, just average API weirdness, acceptable in some way or what? Could it be an error on my part? I'm using C++ Rest SDK for client API access.
The solution, for those who face the same issue, is to change the response header using set_content_type():
if (response.status_code() == status_codes::OK)
{
response.headers().set_content_type(L"application/json");
return response.extract_json();
}
The actual request uses:
http://open.api.sandbox.ebay.com/shopping?callname=GeteBayTime&responseencoding=JSON&appid=<my appid>&siteid=0&version=713
I received a good response at https://casablanca.codeplex.com/discussions/470633. I believe there's more room for discussion. Until then, this will be the standing answer.
I am trying to use cpp-netlib in a project of mine. I simply need to create a HTTP proxy into which I can plug in some functionality later. For now, I just need to listen to requests, send request to a new site, and forward the answer of the new request to the first request.
This is the code I have so far:
std::string ip = source(request);
http::client client;
std::ostringstream url;
url << "www.example.com/image.jpg";
http::client::request clientRequest(url.str());
http::client::response clientResponse = client.get(clientRequest);
response = server::response::stock_reply(server::response::ok);
response.headers = clientResponse.headers(); //This is not possible - not correct type or something
response.content = clientResponse.body();
Results in error C2679: binary '=' : no operator found which takes a right-hand operand of type 'std::multimap<_Kty,_Ty>' (or there is no acceptable conversion)
A request to the test image I am using yields 19.4kb data in the response. If I do the same request through the above code (without header copying) I get an answer with about 4kb data, which the browser tries to show as text (default header). It does seem like an image though, even in text.
Anyone out there that is familiar with cpp-netlib-0.8? is response.content = clientResponse.body(); the correct way? How can I add the correct headers?
It's altogether too much template weirdness in cpp-netlib for me to understand it right now!
Thanks...
Instead of using:
response.content = clientResponse.body();
the correct way is:
std::string body_content = body(clientResponse);
also, you are using response as variable, while your variable is actually clientResponse
For more examples read cpp-netlib v0.8 documentation