How to send a POST request response back to client (React component)? - express

I'm using React to send a post request to my express server which then returns a response, like so:
app.post('/api/games', function(req, res) {
return res.json();
});
Before I use that response to persist it to a database, I want to be able to see everything within that response. When I console.log it from the server, I get a long list of the JSON object printed, but would ideally like something closer to Chrome's dev tools console where I can click through and inspect everything. How can I send this response JSON back to my React component so that I can console.log it in in the browser?
Thanks!

You can use node-inspector in order to debug your express API.
It uses Chrome Dev Tools so you'll feel like you are debugging your client side!

Remember, a request comes in, and the response goes out.
on a request, the req.body and req.params will contain the body/params of the request.
To respond to a request, use the res.json({someJSONHere}) or you can also res.send({someJson})
You can also console.log inside the server and watch output on the terminal
app.post('/api/games', function(req, res) {
console.log(req.params)
console.log(req.body)
return res.json(
Object.assign({}, req.body, req.params)
);
});
Express request/response Documentation

If you want to view your response in the client-tier here are some of the things you can do using the GoogleChrome asides from the console
1 Use React Developer Tools
2 I like using Postman for viewing and manipulating request/response

Related

Expressjs send content after listen

I want to make a route in express js to send some content after 1000 ms.
Note: I cant use res.sendFile, it has to be a plain route.
This is the code for the route:
app.get('/r', (req,res)=>{
res.send("a")
setTimeout(()=>{
res.send("fter")
}, 1000)
}
app.listen(8080)
But I get the error: ERR_HTTP_HEADERS_SENT, I assume because the page has already been loaded.
I need my node program to send it after it has already been loaded, so I cant like send a html,js,css script to do it. Is it possible? I cant seem to find how.
Well, if that is not possible, what I am really trying to do is after the page has loaded, execute js or send a message that the page can receive from the node program, like if there was res.execute_js('postMessage(1)')
EDIT based on your edit: So as I understand you want a way to send different values from a node app endpoint without using socketio. I've managed to replicate a similar experimental behavior using readable streams. Starting off, instead of returning response to the request with res.send() you should be using res.write() In my case I did something like this:
app.post('/api', (req, res) => {
res.write("First");
setTimeout(() => {
res.write("Second");
res.end();
}, 1000);
});
This will write to a stream "First" then after 1000ms it'll write another "Second" chunk then end the stream, thus completing the POST request.
Now in the client, you'll make the fetch response callback async, get the ReadableStream from the request like so
const reader = response.body.getReader();
now we should be reading this stream, we'll first initialize an array to collect all what we're reading,
const output = [];
now to actually read the stream,
let finished, current;
while (!finished) {
({ current, finished} = await reader.read());
if (finished) break;
output.push(current);
}
if you read current in the loop, it'll contain each value we passed from res.write() and it should read twice, "First" and after 1000ms "Second".
EDIT: This is very experimental however, and I wouldn't recommend this in a production codebase. I'd suggest trying out socketio or a publish/subscribe mechanism instead.
Old answer: You're already sending "a" back, you should remove the first res.send() invocation at the top of the callback.
So, this is for all the people wondering. No you cannot do this with pure express (there is a workaround, so keep reading).
The reason you cant do this is because, when the user requests to the url, it sends them a response, and the browser renders it. You cant then tell it to change the response, as the browser has already received a response. Even if you send multiple, like with res.write, rather then res.send, the browser will just wait until it receives all the data.
Here are two workarounds:
    1. Use socket.io, cscnode, or another library to have events for updating text,
    2. Send hardcoded html, that updates text (1 was probably better)
That is all I think you can do.
More clarification on the socketio one is basically have an event for changing text that you can fire from node, and the browser will understand, and change the text.

How to wait for XHR to 3rd party API in Cypress?

I have a SPA application that talks with API that deployed on another server. For example, when I click a Submit button it sends XHR request to it API, and I need to wait for a response to check it. How can I do this?
Put this in cypress/support/commands.js:
Cypress.Commands.add('manageMyApiRequests', () => {
cy.route('/URL/Of/api/I/Want/To/wait/For').as('myApi')
});
Then in your test or before each call:
cy.server();
cy.manageMyApiRequests();
Then where-ever you want to wait for that api response just do:
cy.wait('#myApi');
The same can also be acheived without the first cypress command manageMyApiRequests but I suggest you use this for better organization of your tests and then later you can also add more apis to the same function.
FYI you can also use .then() it if you want to check something within the response:
cy.wait('#myApi').then((xhr) => {
// we can now access the low level xhr
// that contains the request body,
// response body, status, etc
});

Omitting credentials on react native fetch

Im trying to stop the react-native implementation of fetch to send the cookie to the server as i'd like to supply my own custom logic for it. I would expect that
const response = await fetch(apiURL, {
method: 'GET',
headers,
credentials: "omit",
});
would do the trick but it clearly doesnt work as when i inspect the outbound traffic with Wireshark the Cookie gets sent anyway..
Any clues? I'd rather not have to dive into the fetch implementation code but im starting to entertaing the idea..

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

How To Overcome CORS issues with Redux React Express and Node?

I have a React App that uses React Router and Redux as its state manager. The server side of the app uses Express and Node.
I am making API calls to an external service. I do not have the ability to enable CORS on the external service. Therefore, I need to use my app's server side to make the calls to the external service to remove the browser from the equation, and eliminate any CORS error.
I am able to get my data from the service on the server side successfully. I would like to know if it is possible to share the Redux store in between the client and server with some sort of middleware (looking for examples/resources).
The goal:
1) Handle a click event in the client
2) Have that event call a server side route to external api (don't know how to do this)
3) Then the server handles this route, makes the request, and sends the response to the client (through the shared react store - not sure if this is possible)
4) The store gets the new state, and then sends to the client side components, and the UI updates
Are there any examples/tutorials of this? Not looking for an initial server rendered page, but guides that inform how the above 4 steps can generally be implemented.
Thanks for the suggestions.
It turns out that I was severely over thinking the solution. All I really needed was the ability to launch a server side function (get resources from external API) from the client side event (load component). Sort of like how submitting a form, has an action that launches a server side function.
In my component:
componentDidMount() {
const product_api_results = productApi.getProductItems()
console.log('product_api_results in CART Component: ', product_api_results)
/* now I have results and can put it in the Redux Store via action to reducer for other components to work with on client */
}
The productAPI.getProductItems() that the component calls:
export function getProductItems () {
return axios.get('/api/get-products') // triggers a server side route
.then(function (response) {
console.log('client side response: ', response)
return response
})
}
In Express server.js file, the server will see this url and then get the proper data. The shopify.get() is from the shopify-node-api module:
app.get('/api/get-products', function (req, res) { // '/api/get-products' called from client
shopify.get('/admin/products.json', function (err, data, headers) {
res.send(data)
})
})