I'd like to start multiple HTTP requests rapidly after each other, without having to wait on the previous response to arrive. I've tried this using WebClient.UploadStringAsync, but this doesn't work. I'd like to efficiently implement the following scenario:
Send request 1
Send request 2
Send request 3
And in another thread:
Receive response 1
Receive response 2
Receive response 3
Can this be done in Silverlight?
I'd like to start multiple HTTP requests rapidly after each other, without having to wait on the previous response to arrive
That's called HTTP Pipelining (assuming you hope to use the same socket) and it's not supported by many proxies and gateway devices. I would be surprised if Silverlight tried to support it.
Yes it can be done. What leads you to believe that UploadStringAsync isn't working?
Here is my guess you are posting to ASP.NET with Sessions turned on (the default) right?
The requests will be queued at the server end because ASP.NET will only process one request for a specific Session at a time.
Related
I am using fetch in a NodeJS application. Technically, I have a ReactJS front-end calling the NodeJS backend (as a proxy), and then the proxy calls out to backend services on a different domain.
However, from logging errors from consumers (I haven't been able to reproduce this issue myself) I see that a lot of these proxy calls (using fetch) throw an error that just says Network Request Failed, which is of no help. Some context:
This only occurs on a subset of all total calls (lets say 5% of traffic)
Users that encounter this error can often make the same call again some time later (next couple minutes/hours/days) and it will go through
From Application Insights, I can see no correlation between browsers, locations, etc
Calls often return fast, like < 100 ms
All calls are HTTPS, non are HTTP
We have a fetch polyfill from fetch-ponyfill that will take over if fetch is not available (Internet Explorer). I did test this package itself and the calls went through fine. I also mentioned that this error does occur on browsers that do support fetch, so I don't think this is the error.
Fetch settings for all requests
Method is set per request, but I've seen it fail on different types (GET, POST, etc)
Mode is set to 'same-origin'. I thought this was odd, since we were sending a request from one domain to another, but I tried to set it differently and it didn't affect anything. Also, why would some requests work for some, but not for others?
Body is set per request, based on the data being sent.
Headers is usually just Accept and Content-Type, both set to JSON.
I have tried researching this topic before, but most posts I found referenced React native applications running on iOS, where you have to set some security permissions in the plist file to allow HTTP requests or something to do with transport security.
I have implement logging specific points for the data in Application Insights, and I can see that fetch() was called, but then() was never reached; it went straight to the .catch(). So it's not even reaching code that parses the request, because apparently no request came back (we then parse the JSON response and call other functions, but like I said, it doesn't even reach this point).
Which is also odd, since the request never comes back, but it fails (often) within 100 ms.
My suspicions:
Some consumers have some sort of add-on for there browser that is messing with the request. Although, I run with uBlock Origin and HTTPS Everywhere and I have not seen this error. I'm not sure what else could be modifying requests that would cause it to immediately fail.
The call goes through, which then reaches an Azure Application Gateway, which might fail for some reason (too many connected clients, not enough ports, etc) and returns a response that immediately fails the fetch call without running the .then() on the response.
For #2, I remember I had traced a network call that failed and returned Network Request Failed: Made it through the proxy -> made it through the Application Gateway -> hit the backend services -> backend services sent a response. I am currently requesting access to backend service logs in order to verify this on some more recent calls (last time I did this, I did it through a screenshare with a backend developer), and hopefully clear up the path back to the client (the ReactJS application). I do remember though that it made it to the backend services successfully.
So I'm honestly not sure what's going on here. Does anyone have any insight?
Based on your excellent description and detective work, it's clear that the problem is between your Node app and the other domain. The other domain is throwing an error and your proxy has no choice but to say that there's an error on the server. That's why it's always throwing a 500-series error, the Network Request Failed error that you're seeing.
It's an intermittent problem, so the error is inconsistent. It's a waste of your time to continue to look at the browser because the problem will have been created beyond that, either in your proxy translating that request or on the remote server. You have to find that error.
Here's what I'd do...
Implement brute-force logging in your Node app. You can use Bunyan, or Winston or just require(fs) and write out to some file when an error occurs. Then look at the results. Only log it out when the response code from the other server is in the 400 or 500 ranges. Log the request object and the response object.
Something like this with Bunyan:
fetch(urlToRemoteServer)
.then(res => res.json())
.then(res => whateverElseYoureDoing(res))
.catch(err => {
// Get the request & response to the remote server
log.info({request: req, response: res, err: err});
});
where the res in this case is the response we just got from the other domain and req is our request to them.
The logs on your Azure server will then have the entire request and response. From this you can find commonalities. and (🤞) the cause of the problem.
Suppose my back-end is using two (legacy) APIs the responses of which I want to combine. One returns the majority of the data and is quite fast. The other is slow, and only returns one feature for the dataset. Also, the response of the first API is required for the request to the slow API to be meaningful.
What I'd like to do, is that the back-end would return the result of the fast API instantly, then wait for the slow API, and then combine the two into a second response also containing the missing feature. If I'm correct, this would be accomplished somehow with the asynchronous HTTP pattern. However, I'm having troubles conceiving a solution while still keeping my API stateless, like all REST APIs should be.
So far: the following is the best concept I have been able to come up with:
A client (browser) sends a request to my API.
My API retrieves the data from the fast API, and sends a response like: {dataFromFirstAPI: {...}, linkToPoll: "/api/whatever/xyxzzy"} with status 202.
My API sends a request to the slow API, waits for response, processes the response and combines it with the result from the fast API. After that it returns the data to a request at linkToPoll.
Meanwhile the client will poll linkToPoll until it receives an appropriate response and body.
I have a few questions about the above approach:
Is it an antipattern to also return some other data in a 202 response (point 2. above)?
Is there any convention on what the polling URL should be?
One approach would be for the client to send two requests, but this would create state for my API.
What I am trying to achieved is:
Send http 102 to client who requested somedoc.html
Some processing on the side including out of band authentication
If authenticated, send response built from somedoc.html, otherwise generic not auth message
I'm having a failure of understanding somewhere, in that I cannot seem to figure out how to send the 102 and save the connection details so that I can forward the response in step 3. I had thought I could queue a response then either enter a wait loop or suspend the connection, but as far as I can tell I have to return from the MHD_AcceptPolicyCallback for the response to be sent, then I cannot figure out how to get back to the connection. I have looked at the request completed call back but this still results in the 102 not being sent.
I really can't figure out a process to achieve these steps from the examples or the manual and any help would be appreciated.
HTTP standards doesn't define response code 102.
See https://www.rfc-editor.org/rfc/rfc7231#section-6
and https://www.rfc-editor.org/rfc/rfc2616#section-6.1.1
HTTP protocol use request-response logic. If you already responded to some request then you can't add another response later to the same request.
After talking with the developer, the 102 status code was defined "for completeness"; however, no attempt has been made to implement the required functionality to actually be able to use this status code in a meaningful way on a server developed with the libmicrohttpd library.
I am using express-jwt to build a restful api. Now the client is making duplicate ajax calls, for the first one the initiator is angularjs and for the second one the initiator is other. The first one gets 204 as the response code and the second one gets 200 as the response code. I tried to debug to get to the source of this duplicate requests, but I am not able to.
Below is the header details for the one with 204 status code
Below is the header details for the one with 204 status code
Can any one suggest what could be the issue?
The first call is OPTIONS type. That's a pre-flight call which a browser sends if the page and api are not on same domain.
The purpose of this call is to deal with CORS. Backend usually needs to send the allowed request method types (GET, POST etc.). The browser will then send the real call if the desired request type is among those returned.
Here's a sample of the response headers.
You can ignore it for all intents and purposes. It does not contain any normally useful payload or return data.
Take a look at AJAX in Chrome sending OPTIONS instead of GET/POST/PUT/DELETE? for more info.
Those two requests are different one is OPTIONS and other is GET.
For cross-domain requests, setting the content type to anything other than application/x-www-form-urlencoded, multipart/form-data, or text/plain will trigger the browser to send a preflight OPTIONS request to the server.
You need to handle in the server when the request method OPTIONS , then you need to exit with out processing.
We would like to call a websphere web service from silverlight.
If I have understood it correctly:
Silverlight only supports async web service calls
Websphere does not support async calls
Is this correct?
Is it possible to call websphere web services from silverlight?
A general answer to your first question: There is no need for a webservice server to support asynchronous calls. Because HTTP is stateless, the server handles one request in one thread.
Generally speaking, the client can choose whether to wait for the response (synchronous) or to let a new thread wait for the response and do other things meanwhile (asynchronous).
The decision of doing synchronous or asynchronous calls is therefore only part of the client.
It should be possible.
Silverlight is asynchronous only in that the HTTP Web Request (GET, POST) is not linked to the receipt of the the HTTP response. You send an HTTP Request which is one action and separately from the Request you receive and handle the HTTP Response, you don't send a request then wait on the same thread for a response.
On your web server it makes no difference how you receive the request and send the response, so it could be handled synchronously or asynchronously, the Silverlight app would be oblivious to that.
Saying that 'Silverlight only supports async web service calls' only means that it does not block the calling thread while waiting for a response. The request is sent on one thread, the response is received on another thread.