Could someone please explain to me how this line works:
https://github.com/sveltejs/realworld/blob/master/src/routes/login/index.svelte#L13
const response = await post(auth/login, { email, password });
post is being called from utils.js, which is this:
utils.js
export function post(endpoint, data) {
return fetch(endpoint, {
method: 'POST',
credentials: 'include',
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json'
}
}).then(r => r.json());
}
So the function enters here, and then fetches the endpoint provided, which was auth/login.
This confuses me becauseauth/login is not an endpoint, it's a file that exports a function, under auth/login.js. Does this second post function in auth/login.js get called automatically? I am unsure where this (req, res) gets passed in as well, since we are just fetching this file from above and not passing any arguments.
auth/login.js
import * as api from 'api.js';
export function post(req, res) {
const user = req.body;
api.post('users/login', { user }).then(response => {
if (response.user) req.session.user = response.user;
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify(response));
});
}
This is where the user is being set in a cookie, which my code isn't currently doing, and the session is lost upon refresh. I am trying to understand how to persist sessions in Sapper.
This line is making a call to a relative path:
const response = await post(auth/login, { email, password });
So the url that fetch is calling is something like : http://yourdomain.com/auth/login
According to the docs, what happens when a route ending in .js is called is that Sapper looks for a function with the name of the HTTP request method on that file.
More info here : sapper.svelte.dev/docs#Server_routes
Related
I use NextJS (combined: SSR and SPA for authorized dashboard) with Django Rest FW on the backend. For auth I use JWT token, which is stored in cookies. For that reason, I need a middleware at /pages/api/* for each request to append from cookie access token.
Question:
How to implement a protected request to send file to /pages/api/upload and send it to DRF with an access token?
Sample of small API middleware
export default async (req, res) => {
const { id } = req.query
const cookies = cookie.parse(req.headers.cookie ?? "");
const access = cookies["access"] ?? false;
if (access === false) {
return res.status(401).json({
error: "User unauthorized to make this request"
});
}
if (req.method === "GET") {
try {
const apiRes = await fetch(`${LOCAL_API_URL}/items/${id}`, {
headers: {
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": `Bearer ${access}`
}
});
const data = await apiRes.json();
if (apiRes.status === 200) {
return res.status(200).json(data);
} else {
return res.status(apiRes.status).json({
error: data.error
});
}
} catch(err) {
console.log(err);
return res.status(500).json({
error: "Something went wrong"
});
}
} else
res.setHeader("Allow", ["GET"]);
return res.status(405).json({
error: `Method ${res.method} is not allowed`
});
}
For sending image you should use FormData.
Firstly create an instance of FormData.
const formData = new FormData()
Then, you can add image into that.
formData.append('fieldName', someFileInput.current.files[0])
Also, if you want to add some more data with the image, you can append it to FormData too, the similar way.
formData.append('fieldName', someMoreData)
Then, you should set Content-Type to 'multipart/form-data', this is to server understand you pass the FormData.
And, finally, send the form data via Fetch.
I was glad to answer you, I hope it helps you!
the solution was raiser simple. Just passed everything I received and appended token to headers/
export default async (req, res) => {
// all extra validation
const apiRes = await fetch(`${LOCAL_API_URL}/upload/`, {
method: "POST",
headers: { ...req.headers, ...{ "Authorization": `Bearer ${access}` } },
body: req.body
});
// all extra validation
}
I am trying to implement a Discord-Login onto my Website. Unfortunately I am getting an error from discord.
Does anybody see, whats wrong with my code?
FYI: I am already get back the code from discord. So my first request is working fine.
What I want to do with the Data:
I want to get the user_ID so I can add groups to the user on my Discord Server.
ERROR:
error: 'unsupported_grant_type',
error_description: 'Grant type None is not supported'
Code:
router.get('/account-settings/connections/discord/callback', (async (req, res) => {
const code = await req.query.code;
const creds = btoa(`${CLIENT_ID}:${CLIENT_SECRET}`);
fetch(`https://discordapp.com/api/oauth2/token`, {
method: "POST",
headers: {
Authorization: `Basic ${creds}`,
},
body: querystring.stringify({
grant_type: 'authorization_code',
code: code,
redirect_uri: dis_redirect
}),
})
.then((res) => res.json())
.then((body) => console.log(body));
})
Thank you very much in advance!!!
The best regards,
Joshy
Okay for everybody else, who has this problem. I was able to fix this with parsing all information in the body and setting up the content type in the headers. Here is a working code:
let params = new URLSearchParams();
params.append('client_id', CLIENT_ID);
params.append('client_secret', CLIENT_SECRET);
params.append('grant_type', 'authorization_code');
params.append('code', code);
params.append('redirect_uri', dis_redirect);
fetch('https://discord.com/api/oauth2/token', {
method: 'post',
body: params,
headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Accept': 'application/json' },
}).then(r => r.json()).then(async Response => {
In the code variable, I have stored the request query, I am getting back from TwithOauth (After autorization of the user).
Client ID and Client Secret you will get from your Discord Application. The dis_redirect virable is containing my redirection link, which is just blank string of my Link, I have setup to get the router.
Nothing more is needed.
You will get a JSON responded, which you can work with. If you want to get the users data (like me) this following code is what you searching for:
let refresh_token = Response.refresh_token;
let accessToken = Response.access_token;
var site = await fetch("https://discord.com/api/v9/users/#me", {
method: 'GET',
headers: {'Authorization': `Bearer ${accessToken}`}
});
var response = await site.json();
console.log(response);
});
This code you will place directly in the new opened async function. There you have it. All users data, you will need.
I hope I was able to help someone. If you have any questions, just let me know!
The best regards,
Joshy
I am developing a web application using a React frontend and a Node.js backend. The frontend sends a POST request to the backend using Axios like this:
Register.js
...
handleSubmit = (e) => {
e.preventDefault();
const { email, password, name, dateofbirth } = this.state;
const user = { email, password, name, dateofbirth };
const url = "http://localhost:9000/register";
axios
.post(url, user, {
headers: {
"Content-Type": "application/json",
},
})
.then((response) => console.log(response))
.catch((error) => {
console.error("You have made a big error. " + error);
console.log(user);
});
};
...
While the backend receives the request like this:
./routes/register.js
...
router.post("/register", async (req, res) => {
console.log("Inside Home Login");
res.writeHead(200, {
"Content-Type": "application/json",
});
console.log("Users : ", JSON.stringify(users));
res.end(JSON.stringify(users));
})
...
However I get the error "POST http://localhost:9000/register 404 (Not Found)" upon trying to send anything.
My guess would be that you are routing in your index.js. If you can provide a code sample to figure it out.
If so, the thing is defining a routing like,
app.use('/register', yourImportedVariable);
does define a route at http://localhost:9000/register.
So, if in your routes/register.js file you define a GET endpoint with '/register' your front-end call must be http://localhost:9000/register/register
To fix it, either rename your route as '/', or fix your front-end call with the above url.
I'm trying to create a login form using sapper, but am encountering the following problem when trying to test a basic POST fetch.
In routes/login/login.svelte, I have the following code which is called on a button click:
<script>
let data = {"email":"test"};
const handleLogin = async () => {
const response = await fetch("/login/login", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: data
});
};
</script>
Which should send what is in data to routes/login/login.js which has the following code:
export async function post(req, res, next) {
res.setHeader('Content-Type', 'application/json');
var data = req.body;
return res.end(JSON.stringify(data));
}
My problem is that this only returns {} rather than the data sent in the svelte page. Any ideas as to why this is happening and where I'm going wrong? Thanks.
When sending the data, you should also stringify it there
body: JSON.stringify(data)
as an extra make sure you have body-parser installed and added as middleware in the server, this package will help you handle requests that have send json data in their body.
polka() // You can also use Express
.use(
compression({ threshold: 0 }),
sirv('static', { dev }),
bodyparser(),
sapper.middleware()
)
.listen(PORT, err => {
if (err) console.log('error', err);
});
Building on the previous answer, I'm writing here the full working solution. Your problems may be due to:
Not using the json parse middleware
Not treating fetch as a promise
Here's how I'd fix it:
npm i body-parser
Add the json middleware in your server.js
const { json } = require('body-parser');
polka()
.use(
compression({ threshold: 0 }),
json(),
sirv('static', { dev }),
sapper.middleware()
)
.listen(PORT, err => {
if (err) console.log('error', err);
});
Treat the fetch response as a Promise. This is how your Svelte component should look like (notice the chained then):
<script>
let data = {"email":"test"};
const handleLogin = async () => {
await fetch(`your-endpoint`, {
method: 'POST',
body: JSON.stringify(data),
headers:{
'Content-Type': 'application/json'
}
})
.then(res => res.json())
.then(res => console.log(res)); // {email: "test"}
};
</script>
I'm creating a simple ReactJs and I created a Searchbar component that does a post request when the user types something into the searchbar. This is the function that does the call:
const searchApi = searchTerm =>
axios.post('http://localhost:3000/findMovie', {
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
params: searchTerm
});
and it is being called in the onChange function like this:
handleInput = async (ev) => {
const value = ev.target.value;
const resultsBody = await searchApi(ev.target.value);
and this is what I do in my server.js file:
app.post('/findMovie', (req, res) => {
console.log('request:', req.params);
// axios.get('http://www.omdbapi.com/?apikey='+
// process.env.OMDB_API_KEY + '&s=' +)
})
I expected the console.log in the backend to show me the request parameters so that I can later do my api call to the external api and return the results, but the console.log show an empty object.
I'm quite new to this but shouldn't I do a post request for something like this? I also tried the same with a get request but it also didn't work.
Your problem is caused by naming confusion between axios and express. params property in axios is sent as search parameters in the url.
In express url search parameters are available through query property, not params. So, try this:
app.post('/findMovie', (req, res) => {
console.log('request:', req.query);
})
params property on an express request object refers to named route parameters, as in /users/:userId/edit.
More on that in express docs: https://expressjs.com/en/guide/routing.html#route-parameters
Update
Also, in order for the axios.post method to work properly, you need to change your call a little bit. It expects the post data a second argument. Since you're not sending any data in the body, you can provide an empty object:
const searchApi = searchTerm =>
axios.post('http://localhost:3000/findMovie', {} /* <-- this guy */, {
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
params: searchTerm
});
Without it, your config object is wrongfully treated as post data.
Try your axios function like this, set the params property as an object:
const searchApi = searchTerm =>
axios.post('http://localhost:3000/findMovie', {
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
params: { searchTerm }
});
And on the server you need to use req.query:
app.post('/findMovie', (req, res) => {
console.log('request:', req.query);
})
You should be able to get the param as req.query.searchTerm