What exactly does the expected HTTP response for a Reverse-AJAX request look like? - xmlhttprequest

I'm trying to implement a simple Web Service (running on an Arduino board using an Ethernet shield) that can provide (push) information to a subscribed client by means of Reverse-AJAX.
The web service hosts a single web page that presents information from a (2D-LIDAR) sensor connected to that server board. Whenever the sensor output changes (very frequently and rapidly) the clients viewing that page should be instantly updated. For this application Reverse-AJAX / AJAX Push seems to be the option of choice, however I'm struggling to get the server part working.
This is what's in my aforementioned web page to "listen" for updates:
var xhr = new XMLHttpRequest();
xhr.multipart = true;
xhr.open( 'GET', 'push', true) ;
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
processEvents( window.JSON.parse( xhr.responseText ) );
}
}
xhr.send( null );
I'd like to keep the XmlHttpRequest running forever and have it call the processEvents function whenever a chunk of (JSON) data comes in from the server side. However I'm not sure what the server response, especially the HTTP response header should look like to make this work as expected.
Whenever I have the server send a HTTP response header like this
HTTP/1.1 200 OK\r\n
Connection: keep-alive\r\n
Content-Length: 100\r\n
Content-Type: text/json\r\n
\r\n
the XmlHttpRequest finishes after receiving exactly one "chunk" of data. I also tried without "Content-Length" header, but "Content-Type: multipart/mixed; boundary=..." or "Transfer-Encoding: chunked" but both never happened to fire processEvents, supposedly because the browser was waiting for the response to complete, whatever that means.
I'm therefore looking for a working example of such a HTTP Response to an AJAX-Push request. What does a HTTP Response generally need to look like to be accepted by the indefinitely running XmlHttpRequest and to fire processEvents whenever new data arrives?
Btw. I tried those things using Firefox 64.0.

if you a looking for a low latency http based comm you should take a look at websockets. Your xmlhttp with Post method will have a high latency of about 50 milliseconds , trust me, I tried to develop a rgb controller based on a rainbow color picker before, either sync and asynchronous post methods wasn’t working well for me, the script just hold waiting for a response.
Now to answer you question specifically, download postman, a software that allows you to simulate all the http methods requests and headers you wish to. Also gives you the code to implement in many languages, and don’t forget f12 on chrome > network tab, this way you can check how the output of or http requests are being handled

Related

Handling long blocking API calls in ASP.NET Core

I'm building an API that will handle http calls that perform much work immediately.
For example, in one controller, there is an action (Post request) that will take data in the body, and perform some processing that should be done immediately, but will last for about 1 to 2 minutes.
I'm using CQRS, with Mediatr, and inside this post request, I call a command to handle the processing.
Taking this into consideration, I want the post request to launch the command, then return an Ok to the user though the command is still running in the background. The user will be notified via email once everything is done.
Does someone know any best practice to accomplish this?
Though I'm using MediatR, sending the request to the handler, the call is not executed in parallel.
[HttpPost]
public async Task<IActionResult> RequestReports([FromBody] ReportsIntent reportsIntent)
{
await _mediator.Send(new GetEndOfWeekReports.Command(companyId, clientId, reportsIntent));
return Ok();
}
Does someone know any best practice to accomplish this?
Yes (as described on my blog).
You need what I call the "basic distributed architecture". Specifically, you need at least:
A durable queue. "Durable" here means "on disk; not in-memory".
A backend processor.
So the web api will serialize all the necessary data from the request into a queue message and place that on the queue, and then return to the client.
Then a backend processor retrieves work from that queue and does the actual work. In your case, this work concludes with sending an email.
In a way, this is kind of like MediatR but explicitly going out of process with the on-disk queue and a separate process being your handler.
I would handle API calls that takes some time separately from calls that can be completed directly.
when I do API calls that takes time, I queue them up and process them on the backend.
a typical API call can look something like this:
POST http://api.example.com/orders HTTP/1.1
Host: api.example.com
HTTP/1.1 201 Created
Date: Fri, 5 Oct 2012 17:17:11 GMT
Content-Length: 123
Content-Type: application/json
Location: http://poll.example.com/orders/59cc233e-4068-4d4a-931d-cd5eb93f8c52.xml
ETag: "c180de84f951g8"
{ uri: 'http://poll.example.com/orders/59cc233e-4068-4d4a-931d-cd5eb93f8c52.xml'}
the returned URL is a unique url where the client then can poll/query to get an idea about the status of the job.
When the client queries this URL, then it can look something like this:
and when it is later done, the result would be something like:
Where dataurl is a link to the result/report that the client then can download.

HTTP response body for server command request

I am solving one question with my team about REST API specification.
We have a case where in some requests we are sending only some particular command via HTTP request for example : We are using POST (now considering PATCH request) to endpoint : /server/startSomeOperation . Backend developers told us that this request is only telling hardware to start some functionality on backend that affects the measurement of the user but it really has nothing to return. My question is :
Should we (according to some REST API specification) always return body of such a request when we know that no additional returned data will be needed except HTTP status code? Until now we were strictly following the rule that every request needs to have some sort of body returned but until now every body response even when it was a command to a server made sense.
Should we (according to some REST API specification) always return body of such a request when we know that no additional returned data will be needed except HTTP status code?
No - it is perfectly fine to send a 204 No Content or a 205 Reset Content when the semantics of your response is well aligned with the standard meaning of those codes.
You also have the option of declaring that the "representation of the status of, or results obtained from, the action" is zero bytes long, in which case you could use a 200 OK with a Content-Length header.

How to distinguish between GET and POST

I'm writing a simple api for training using express. Here's my testing code:
var express = require('express');
var app = express();
app.post("/api/:var_name", function(req, res) {
res.send(req.params.var_name);
});
is simply testing to see if POST is working. When I call http://localhost:3000/api/1 I get Cannot GET /api/1, so the server is obviously interpreting the POST request as GET, what do I need to do to call POST instead?
Anything you call in the address bar of your browser will be sent via get. This is due to the fact that post-messages (and almost all other methods) do have a body-part. But there is no way for your browser to send additional information inside the body of the http packet.
If you want to test your routes for any method other than GET I would suggest you download a tool like postman.
https://www.getpostman.com/
BEWARE: This is my preference. You can of curse also use text based browsers like curl to test it.
The server interprets the request according to the verb you set in the HTTP request. If no method/verb is specified it is interpreted as GET(not sure about this part).
When you call that URL, you need to use the method as well. For example if you use the fetch API, you can call it like:
fetch(url, {method:"POST"})
If you're entering it in your browser and expect it to be interpreted as a post request, it's not. All browser url requests are GET. Use a tool like Postman to call different HTTP verbs. It's really useful when creating such APIs.
You can check out this answer on details of how to add body and headers to a post request: Fetch: POST json data

Restangular: How to get HTTP response header?

I have a REST server which returns a Link HTTP header with a response to a PUT to indicate the URL of the newly-created entity:
Link:<entities/6>; rel="created"
Is there any possibility to read that link header with Restangular?
The only facility to intercept HTTP requests with Restangular I've met so far is to register a response interceptor in the app config:
restangular.addResponseInterceptor(function (data, operation, what, url, response, deferred) {
console.log(response.headers())
return response.data;
});
However, with above demo implementation in place, the only HTTP header which gets logged is content-type. Still, I can see in the browser development toolbar that a response comes indeed with many additional HTTP response headers, such as Server, Date, and the aforementioned Link.
Why do I not have access to the full array of HTTP response headers through addResponseInterceptor()? Is there any way to capture the HTTP response header in question using Restangular?
Note: I don't search for an answer using HAL or any other special response body format. I would rather like to know whether I can use plain HTTP headers with Restangular or not (if not, I will probably resort to HAL or something).
You don't need a ResponseInterceptor to do this. You just need to set fullResponse to true to get the whole response (including the http headers) every time you do any request.
Restangular.setFullResponse(true);
You can set it globally in your app configuration. Something like this:
angular.module('YourApp')
.config(['RestangularProvider',
function (RestangularProvider) {
RestangularProvider.setFullResponse(true);
...
Then, every time you receive a response, you can access all the response headers.
Restangular.all('users').getList().then(function(response) {
$scope.users = response.data;
console.log(response.headers);
}
Example:
response.headers('Link')
NOTE: Be careful because using fullResponse, the response data is located in response.data, not directly in response.
EDIT: As #STEVER points, you also need to expose the headers in your server API.
Example:
Access-Control-Expose-Headers: Link
You can get more detailed information in Restangular documentation
Hope it helps.

Intercept Requests With Custom Responses in PhantomJS?

Is there a way to intercept a resource request and give it a response directly from the handler? Something like this:
page.onRequest(function(request){
request.reply({data: 123});
});
My use case is for using PhantomJS to render a page that makes calls to my API. In order to avoid authentication issues, I'd like to intercept all http requests to the API and return the responses manually, without making the actual http request.
onResourceRequest almost does this, but doesn't have any modification capabilities.
Possibilities that I see:
I could store the page as a Handlebars template, and render the data into the page and pass it off as the raw html to PhantomJS (instead of a URL). While this would work, it would make changes difficult since I'd have to write the data layer for each webpage, and the webpages couldn't stand alone.
I could redirect to localhost, and have a server there that listens and responds to the requests. This assumes that it would be ok to have an open, un-authenticated version of the API on localhost.
Add the data via page.evaluate to the page's global window object. This has the same problems as #1: I'd need to know a-priori what data the page needs, and write server side code unique to each page.
I recently needed to do this when generating pdfs with phantom js.
It's slightly hacky, but seems to work.
var page = require('webpage').create(),
server = require('webserver').create(),
totallyRandomPortnumber = 29522,
...
//in my actual code, totallyRandomPortnumber is created by a java application,
//because phantomjs will report the port in use as '0' when listening to a random port
//thereby preventing its reuse in page.onResourceRequested...
server.listen(totallyRandomPortnumber, function(request, response) {
response.statusCode = 200;
response.setHeader('Content-Type', 'application/json;charset=UTF-8');
response.write(JSON.stringify({data: 'somevalue'}));
response.close();
});
page.onResourceRequested = function(requestData, networkRequest) {
if(requestData.url.indexOf('interceptme') != -1) {
networkRequest.changeUrl('http://localhost:' + totallyRandomPortnumber);
}
};
In my actual application I'm sending some data to phantomjs to overwrite request/responses, so I'm doing more checking on urls both in server.listen and page.onResourceRequested.
This feels like a poor-mans-interceptor, but it should get you (or whoever this may concern) going.