I'm trying to test HTTP timeout scenarios using a MockWebServer which answers my test requests sent with Retrofit/OkHttp. (This question was asked before some years ago, but at the time concerned a bug in the MockWebServer. Also, the API has since changed a fair bit, so I think reposting this question is warranted.)
There seem to be several related methods, but I'd appreciate a solution to this issue with a clear example: I'm unsure about the difference between..
.delayBody and
.throttleBody
Also, both of these methods seem to only delay/throttle the body - is it not possible to set a timeout for the response header? I.e. something along the lines of "wait X seconds after the next incoming request before you send out any response".
Try setting the response’s socket policy to NO_RESPONSE.
The setSocketPolicy() method is deprecated.
MockResponse mockResponse = new MockResponse().setBodyDelay(10, TimeUnit.SECONDS);
This will delay the MockWebServer response by 10 seconds.
Related
We have a POST endpoint in our serverless api which listens to a Magento 2 integration activation callback and processes the payload. The Content-Type of this callback request is application/x-www-form-urlencoded. However, when we try to get the callback, the lambda function finishes execution immediately, skipping the entire function body. What we see in the Cloudwatch logs is only this. Not even console.logs are printed. (the endpoint only prints a string to the console. No async operations are in place. Yet this problem persists)
2020-12-12T12:24:47.012+05:30 START RequestId: 4afba03d-54ef-4b5e-bd44-157b0b7a9f9b Version: $LATEST
2020-12-12T12:24:47.050+05:30 END RequestId: 4afba03d-54ef-4b5e-bd44-157b0b7a9f9b
2020-12-12T12:24:47.050+05:30 REPORT RequestId: 4afba03d-54ef-4b5e-bd44-157b0b7a9f9b Duration: 37.83 ms Billed Duration: 38 ms Memory Size: 128 MB Max Memory Used: 109 MB Init Duration: 893.79 ms
When we try to hit the same endpoint from POSTMAN with Content-Type: application/json, the endpoint works as expected.
Therefore we thought that the problem might be the Content-Type header and read somewhere that adding request mapping templated would solve this problem. Therefore, we even added a mapping template for content type application/x-www-form-urlencoded in the integration request of the lambda method with following content, time to time. But our problem was not solved unfortunately.
"{ "body": "$util.base64Decode($input.body)" }"
{
"formparams" : $input.json('$')
}
{
"body" : $input.json('$')
}
My question is: How we can set the endpoint to print the POST request payload, preventing it from immediate exiting?
We have been searching for a solution to this problem since a week. It would be a great help, if someone can input their helpful, valuable suggestions to solve this problem. Thanks in advance
Since the Content-Type of the Magento 2 Integration activation callback is application/x-www-form-urlencoded, the lambda event for that POST request was something like this.
console.log(event) -> {body: "a=var&b=other_var&c=another_var"}
The endpoint didn't even print anything because I had put console.log(JSON.parse(event. body)). This results in a JSON parse error and the endpoint immediately finishes execution.
When I started parsing the query parameter event body instead of JSON.parse(), the problem was solved.
I'm trying to post a user status update to the Goodreads API.
Most of the time my request returns 200 OK and does nothing. Every now and then, though, it returns 201 Created and the status is updated. When it works it's always the first time I try to make the call after running the app in iOS simulator. Subsequent calls never work.
I don't think the problem is the API itself, since the official Goodreads iOS app uses the same call and it always works.
Their API is famous for having problems with calls that include brackets in the parameters, but I can make other calls that contain brackets and they work fine, the problem is just this one.
I'm using OAuthSwift and this is my code:
oAuth.client.post(
"http://www.goodreads.com/user_status",//.xml",//?user_status[book_id]=6366035&user_status[page]=168",
parameters: ["user_status[page]" : 168, "user_status[book_id]" : 6366035, "format" : "xml"],
//headers: ["Content-Type" : "application/x-www-form-urlencoded"],
success: {
data, response in
print("")
print(response)
},
failure: {
error in
print("")
print(error)
}
)
(The commented out parts are alternatives I have tried unsuccessfully.)
I'm printing the base string that gets signed and it looks the same for the calls that work and the ones that don't, except for the nonce and the timestamp, obviously.
In the headers is also included the oauth_signature, which changes every time and sometimes contains characters that are encoded by OAuthSwift, so that could account for the call working just some of the time (it could work only when the signature doesn't contain a certain character)… but I'm printing out the headers too and I don't see any patterns or any discernible difference between the headers of the calls that work and those of the calls that don't.
So now I don't know what to test anymore… I'm checking the base string and the headers for calls that work and for calls that don't and they look the same… Could anybody think of something else that changes between calls and I should check? I have no idea what could be causing this and I don't know how to debug it.
Thanks in advance,
Daniel
Edit: Very weird… I tried my request with Paw, a Mac REST client, and with Chrome's Postman extension. If I use https I get 404 on my first call, then 201 on the second, then 404 on the third, 201 on the forth and so on. It works every other time. The time it works it doesn't matter if I use http or https, it works as long as there was a failed https request just before.
So I tried doing the same in my app: I added two https calls one after the other… in my app they always return 404.
So it seems like Postman, Paw and OAuthSwift are handling the requests differently. I don't know what could be the difference between those clients… the signature base string seems to be the same for all three, the headers too… so what else could change between them?
In the newer versions of Xcode you can only communicate with a HTTPS server. I expect Google support that so you can change the URL. Or you can edit your Info.plist file.
App Transport Security Settings > Allow Arbitrary Loads > YES
Doing scraping I've found that some urls failed. After check the url looked ok in the browser and see in wireshark the remote server was answering with a 200 I've finally found that the url:
http://www.segundamano.es/electronica-barcelona-particulares/galaxy-note-3-mas.htm
was failing with
Net::HTTP::Persistent::Error: too many bad responses after 0 requests on 42319240, last used 1414078471.6468294 seconds ago
More weird is that if you remove a character from the last part, it works. If you add the character in another place, it fails again.
Update 1
The "code"
agent = Mechanize.new
page = agent.get("http://www.segundamano.es/electronica-barcelona-particulares/galaxy-note-3.htm")
Net::HTTP::Persistent::Error: too many bad responses after 0 requests on 41150840, last used 1414079640.353221 seconds ago
This is a network error which normally occurs if you make too many requests to a certain source from the same IP and thus the page takes too long to load. You could try adding a custom timeout to your connection agent, keep the connection alive and ignore bad chunking (potentially bad):
agent = Mechanize.new
agent.keep_alive = true
agent.ignore_bad_chunking = true
agent.open_timeout = 25
agent.read_timeout = 25
page = agent.get("http://www.segundamano.es/electronica-barcelona-particulares/galaxy-note-3.htm")
But that is not giving you a guarantee that the connection will be successfull, it just increases the chances.
It's hard to say why you get the error on one url and not on another. When you remove the 3 you request a different page; one that might be easier for the server to process? My point being: There is nothing wrong with your Mechanize setup but with the response you are getting back.
Agree with Severin, the problem was in the other side. As I can't do anything in the server, I was trying different libs to fetch the data. It was weird that some of them worked and others don't. Trying different setups for mechanize, at the end I've found a good one:
agent = Mechanize.new { |agent|
agent.gzip_enabled = false
}
I am working on a web-project. I have created one Http Url Connection. But for that, I have to test the code for time-out InterruptedIOException, that will execute on time-out, but even after setting time-out time as 1msec, my case is executed successfully.
How can I make delay from SOAPUI, so that I can have time-out successfull?
If you want to test how a client will react to a timeout, create a mockservice in SoapUI, and have it execute an OnRequest script prior to returning the (usually pre-determined) response. The script can be as simple as:
sleep(60000)
This would give you a 60-second delay before responding.
Select your response in the tree.
Then at the bottom in "MockResponse Properties" look for:
If you need to simulate a timeout thrown from an HTTP connectivity,
then better use the script
mockRequest.getHttpResponse().sendError(408)
This will generate an html response as well. You may set any HTTP code status you desire.
You may put it in "OnRequest Script", or in the "Script" of an existing Mock Response.
Use HTTP STatus property of Response Message set the value to 408
I'm implementing a REST API using ASP.NET MVC, and a little stumbling block has come up in the form of the Expect: 100-continue request header for requests with a post body.
RFC 2616 states that:
Upon receiving a request which
includes an Expect request-header
field with the "100-continue" expectation, an origin server MUST
either respond with 100 (Continue) status and continue to read
from the input stream, or respond with a final status code. The
origin server MUST NOT wait for the request body before sending
the 100 (Continue) response. If it responds with a final status
code, it MAY close the transport connection or it MAY continue
to read and discard the rest of the request. It MUST NOT
perform the requested method if it returns a final status code.
This sounds to me like I need to make two responses to the request, i.e. it needs to immediately send a HTTP 100 Continue response, and then continue reading from the original request stream (i.e. HttpContext.Request.InputStream) without ending the request, and then finally sending the resultant status code (for the sake of argument, lets say it's a 204 No Content result).
So, questions are:
Am I reading the specification right, that I need to make two responses to a request?
How can this be done in ASP.NET MVC?
w.r.t. (2) I have tried using the following code before proceeding to read the input stream...
HttpContext.Response.StatusCode = 100;
HttpContext.Response.Flush();
HttpContext.Response.Clear();
...but when I try to set the final 204 status code I get the error:
System.Web.HttpException: Server cannot set status after HTTP headers have been sent.
The .NET framework by default always sends the expect: 100-continue header for every HTTP 1.1 post. This behavior can be programmatically controlled per request via the System.Net.ServicePoint.Expect100Continue property like so:
HttpWebRequest httpReq = GetHttpWebRequestForPost();
httpReq.ServicePoint.Expect100Continue = false;
It can also be globally controlled programmatically:
System.Net.ServicePointManager.Expect100Continue = false;
...or globally through configuration:
<system.net>
<settings>
<servicePointManager expect100Continue="false"/>
</settings>
</system.net>
Thank you Lance Olson and Phil Haack for this info.
100-continue should be handled by IIS. Is there a reason why you want to do this explicitly?
IIS handles the 100.
That said, no it's not two responses. In HTTP, when the Expect: 100-continue comes in as part of the message headers, the client should be waiting until it receives the response before sending the content.
Because of the way asp.net is architected, you have little control over the output stream. Any data that gets written to the stream is automatically put in a 200 response with chunked encoding whenever you flush, be it that you're in buffered mode or not.
Sadly all this stuff is hidden away in internal methods all over the place, and the result is that if you rely on asp.net, as does MVC, you're pretty much unable to bypass it.
Wait till you try and access the input stream in a non-buffered way. A whole load of pain.
Seb