I want to perform a fetch call in order to validate data that comes from the header HTTP call. the data validation happens in a remote server and should check if the user_id that I send exists in the remote server.
I thought creating a middleware and in that middleware create a fetch call that sends the
data to the remote server,
What is the best practice for that scenario?
Is it as I described?
This is a simple middleware I wrote just to describe what I want to do.
export class Eauth implements NestMiddleware {
async use(req: Request, res: Response, next: NextFunction){
const response = await fetch('https://jsonplaceholder.typicode.com/users/1')
console.log(response.status)
next();
}
}
Related
I need to send the req.body (data received from the client to API route via post request) data from the API route to a separate javascript file in the backend api.
const payload = {}
const handler = async (req, res) => {
payload = req.body
res.status(200).json({ status: 'success' })
}
export default handler
I declared a variable outside the route handler function and assigned req.body to it, but then I realized that I can't use this global variable inside the handler function. I don't know the reason. Is there any specific way of achieving what I'm trying to achieve here?
I request to please elaborate the use case a bit more. Based on current requirements.
I can understand that-
You need to send the req.body to another JavaScript file. Now here can be 2 cases.
You need to store req.body in a file, and use it for later processing.
Pass the req.body to another function which is present in another JavaScript file.
In this case, you can export the function from another file and import in this main file and call the function in your controller and pass req.body as Payload.
I think your use case will be second one, if not please update question and I will be happy to help you out.
I am using Axios in my NodeJs application to do HTTP requests.
I am logging in using a post request that does not require a cookie set in the header.
const instance = axios.create({ baseURL: 'https://some_url.com' , withCredentials: true});
const response = await instance.post('auth/login', data);
This returns a set-cookie in its header that I need to use in all subsequent API call. This is code I have tried for this.
const getResponse = await instance.get('/getStuff?$top=10', { withCredentials: true });
This always returns a "Not logged in error". I do not have access to the server, but I am assuming this is because my get request did not send the cookie in its header.
Running all of this in a lambda, not sure if that makes a difference.
Question: How do I get the cookie from my first post request and use it in my get request?
The withCredentials option is for the browser version of axios, and relies on browser for storing the cookies for your current site.
Since you are using it in Node, you will have to handle the storage yourself.
TL;DR
After the login request, save the cookie somewhere. Before sending other requests, make sure you include that cookie.
To read the cookie, check response.headers object, which should have a set-cookie header (which is all cookies really are - headers with a bit of special convention that has evolved into some sort of standard).
To include the cookie in your HTTP request, set a cookie header.
General example
You could also look for some "cookie-handling" libraries if you need something better than "save this one simple cookie I know I'll be getting".
// 1. Get your axios instance ready
function createAxios() {
const axios = require('axios');
return axios.create({withCredentials: true});
}
const axiosInstance = createAxios();
// 2. Make sure you save the cookie after login.
// I'm using an object so that the reference to the cookie is always the same.
const cookieJar = {
myCookies: undefined,
};
async function login() {
const response = await axiosInstance.post('http://localhost:3003/auth', {});
cookieJar.myCookies = response.headers['set-cookie'];
}
// 3. Add the saved cookie to the request.
async function request() {
// read the cookie and set it in the headers
const response = await axiosInstance.get('http://localhost:3003',
{
headers: {
cookie: cookieJar.myCookies,
},
});
console.log(response.status);
}
login()
.then(() => request());
You could also use axios.defaults to enforce the cookie on all requests once you get it:
async function login() {
const response = await axios.post('http://localhost:3003/auth', {});
axios.defaults.headers.cookie = response.headers['set-cookie']
}
async function request() {
const response = await axios.get('http://localhost:3003');
}
As long as you can guarantee that you call login before request, you will be fine.
You can also explore other axios features, such as interceptors. This may help with keeping all "axios config"-related code in one place (instead of fiddling with defaults in your login function or tweaking cookies in both login and request).
Lambda
AWS Lambda can potentially spawn a new instance for every request it gets, so you might need to pay attention to some instance lifecycle details.
Your options are:
Do Nothing: You don't care about sending a "login request" for every lambda run. It doesn't affect your response time much, and the other api doesn't mind you sending multiple login requests. Also, the other api has no problem with you having potentially multiple simultaneous cookies (e.g. if 10 lambda instances login at the same time).
Cache within lambda instance: You have a single lambda instance that gets used every once in a while, but generally you don't have more than one instance running at any time. You only want to cache the cookie for performance reasons. If multiple lambda instances are running, they will each get a cookie. Beware the other api not allowing multiple logins.
If this is what you need, make sure you put the axios config into a separate module and export a configured instance. It will be cached between runs of that one lambda instance. This option goes well with interceptors usage.
const instance = axios.create({...});
instance.interceptors.response.use(() => {}); /* persist the cookie */
instance.interceptors.request.use(() => {}); /* set the cookie if you have one */
export default instance;
Cache between lambda instances: This is slightly more complicated. You will want to cache the cookie externally. You could store it in a database (key-value store, relational, document-oriented - doesn't matter) or you could try using shared disk space (I believe lambda instances share some directories like /tmp, but not 100% sure).
You might have to handle the case where your lambda gets hit by multiple requests at the same time and they all think they don't have the cookie, so they all attempt to login at the same time. Basically, the usual distributed systems / caching problems.
I created graphql lambda by following this instruction: https://www.apollographql.com/docs/apollo-server/deployment/lambda/
It works fine with API gateway. However, I need to call this lambda function from another lambda. I think I need to put ApolloClient in the other lambda function in order to send a graphql request. However, it doesn't work because I can't choose a right link for calling lambda.
So I am looking for how to build the graphql request programatically. I can send the request as an event to trigger the graphql lambda.
Is there a way to do that?
For example, if I have a mutation request like:
mutation sendMessage {
sendMessage(text: "hello"){
text
}
I need to find a way to convert the request to below payload:
{"id":"1","type":"start","payload":{"variables":{},"extensions":{},"operationName":"sendMessage","query":"mutation sendMessage {\\n sendMessage(text: \\"hello\\") {\\n text\\n __typename\\n }\\n}\\n"}}
then I send this payload to the graphql lambda function
You can use graphQL client to perform graphQL request via API Gateway endpoint using HTTP.
Given that you have an API Gateway endpoint pointing to the graphQL server, you can perform a graphQL request to that endpoint from another lambda.
GraphQL queries to the server is simply a regular POST request formatted in a certain way. So if you wanted, you could use any server-side HTTP client to perform that request. However, using a library like graphql-request makes it much simpler.
You can use graphql-request package to perform server-side graphQL requests.
import { request } from 'graphql-request'
const endpoint="https://your-api-gateway-endpoint";
const headers = {
"x-api-key": 'api-gateway-key' // if your endpoint requires API key
};
const client = new GraphQLClient(endpoint, { headers });
const query = `{
mutation sendMessage {
sendMessage(text: "hello"){
text
}
}`;
const data = await client.request(query);
console.log(JSON.stringify(data, undefined, 2));
I can access the session object data when using post method but session object data is null when using get method.How can i access session object data using get method.
I am using express-session.
Front-end Code
For POST method
axios.post(url,{params:data},{withCredentials: "true"})
For GET method
axios.get(url,{params:data},{withCredentials: "true"})
Back-end Code
Middleware for both get and post requests.
router.use((req: Request, res: Response, next: NextFunction) => {
console.log(req);
if (req.session && req.session.username) next();
else res.status(401).send("Unauthorized");
});
axios.get() only takes two arguments (not three). The first is the URL and the second is the options. You are passing the options in the third spot which axios.get() does not look at. Therefore, it never sees the withCredentials: true option and thus doesn't send the session cookie and thus your server doesn't know how to find the session.
So, change from this:
axios.get(url,{params:data},{withCredentials: "true"})
to this:
axios.get(url,{withCredentials: "true"})
Note, there is no data argument for axios.get() because a GET does not send a request body, only a POST or PUT send the body. See the doc here.
Note: This bites people regularly with axios. .post() and .get() need a different number of arguments.
I made a form post request from my react front end. In my express route I handle it, and I send the data to the browser, as such:
app.post("/api/fetchuser", async (req, res) => {
// Doing some stuff here
res.send(req.body.user);
});
My question is: How can I get the data from this POST request route back to my client side? Previously, I did axios.get(...) to retrieve data on a app.get(...) route in a similar fashion, however, this is a POST route. How can I solve this issue?
Just do axios.post request. See Performing a POST request section of axios documentation.
Edit: Yes you can also retrieve data by POST request. You don't have to post any data to the server while performing the request.
axios.post('/api/fetchuser/',{})
.then(res => console.log(res.data));