How to pass array in the url? - javascript

I'd like to filter and want to pass an array to the url.
handleFilter = (search, page = 1) => {
const requestOption = {
method: "GET"
};
fetch("http://127.0.0.1:8000/api/home?search=" + JSON.stringify(search) + "&page=" + page, requestOption)
.then(res => res.json())
.then(data => (
this.setState({
data
})
))
};
Just want to pass the array of data to the api to call the query

I don't know if this will be what exactly you need, but I would...
a.) Join it on a strange character, and pass it as a string.
b.) On the receiving side (client or server), split on that same character.

If you want send it exactly as GET method (not Post), you can form your URL like this:
"http://127.0.0.1:8000/api/home?search[]=value1&search[]=value2&search[]=value3"
That is if you don't want send JSON string.
And what the problem with JSON version or POST method?

Related

Currently learning svelte and need some assistance

Currently I am trying to create a hacker news clone (not from the example given on website). Currently I made an api call that returns an array but I can't seem to get rid of the square brackets. For reference my code is below
onMount(() => {
fetch('https://hacker-news.firebaseio.com/v0/topstories.json?print=pretty&limitToFirst=10&orderBy="$key"')
.then((res) => {
return res.text();
})
.then((text) => {
items = text.split(",");
setTimeout(3000);
data = items.filter((val) => {
return val.replace(/[\[\]']+/g, "");
});
});
//console.log(data);
//getData(items).then(console.log);
});
Thanks in advance!
The API provides a JSON object, but you read it as text (res.text()). Replace this with res.json() and the result will automatically be parsed to an array of IDs.
There is no need to manipulate JSON in string form, just parse it/let it be parsed.

How to get JSON value from PHP?

I'm trying to get JSON value from PHP but if one of the property values contains a forward slash "/" it fails (I'm using GET to send data for this particular scenario).
Here's how I'm sending the data (This works just fine when I don't send "/").
UI side
const dataObj = {
description: 'my / description',
buyer: 'Mike Brown'
};
const dataString = JSON.stringify(dataObj);
fetch(`http://localhost:8000/clients/${dataString}`)
.then((response) => response.text())
.then((responseData) => {
......
});
PHP side:
Route::get('/clients/{data}', function($data) {
// This line below fails ONLY if value of description property contains "/"
// otherwise it works just fine
$dataToBeSaved = json_decode($data, true);
});
Yes, I did some research on json_decode, but nothing very clear. Can anyone point me on the right direction? Thanks a lot in advance!
It's not really a good idea to pass JSON data in a URL, and you can't do it directly because it will contain characters that have meaning in URLs (e.g. /, ?, =, etc.). But if you must you have a couple options:
You can URL encode the string and pass it as a parameter. This wouldn't work with the route you have, but it has the benefit of not needing to do anything else. You can just get the value from the parameter.
const dataObj = {
description: 'my / description',
buyer: 'Mike Brown'
};
const dataString = encodeURIComponent(JSON.stringify(dataObj));
console.log(`https://example.com/clients?data=${dataString}`);
Or you can base64 encode it. This doesn't by default create URL safe strings, so you'll have to replace a few characters to make it URL safe. That also means you'll have to do the reverse on the server. This solution will work with your route.
const base64UrlEncode = function(str) {
return btoa(str)
// this character have meaning in URLs so we need to replace them
// with something else. we'll have to reverse this on the server.
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=+$/, '');
};
const dataObj = {
description: 'my / description',
buyer: 'Mike Brown'
};
const dataString = base64UrlEncode(JSON.stringify(dataObj));
console.log(`https://example.com/clients/${dataString}`);
And to decode on the server:
function base64UrlDecode($encodedStr) {
// undo the character replacements we did when encoding the string
$unreplace1 = str_replace('-', '+', $encodedStr);
$unreplace2 = str_replace('_', '/', $unreplace1);
return base64_decode($unreplace2);
}
Route::get('/clients/{data}', function($data) {
$dataToBeSaved = json_decode(base64UrlDecode($data), true);
});
One thing to note with this solution is that web servers usually have a limit for the length of URLs (e.g. Apache's default is 8,177 characters). Also, there is usually a limit to the size of the "filename" in the URL (the last component in the path). Apache's default is 255 bytes/characters. So if your base64 encoded JSON is longer than 255 characters, it won't work. A better solution is to pass the data as part of the request body (i.e. as a POST request). That way you won't have a limit and you won't need to encode it beyond converting it to JSON.

How to handle null URL parameters with Express.js

I'm working on an assignment for my web services class and can't figure out how to handle a null URL parameter. Here is my code:
app.get('/nachos/:x/:cheese/:tomatoes/:salsa/:hotsauce', (req, res) => {
var x = parseInt(req.params['x'])
var cheese = (req.params['cheese'])
var tomatoes = (req.params['tomatoes'])
var salsa = (req.params['salsa'])
var hotsauce = (req.params['hotsauce'])
res.send('You ordered ' + x + ' nacho(s) with ' + cheese + ', ' + tomatoes + ', ' + salsa + ', '
+ hotsauce + '.')})
This code works fine with all parameters filled. But how do I handle a null parameter if I don't want, for example, salsa and type in the url localhost:port/nachos/1/cheese/tomatoes/hotsauce
If I'm reading correctly the question is:
How do I handle a null parameter if I don't want, for example,
salsa and type in the url localhost:port/nachos/1/cheese/tomatoes/hotsauce
You won't get null it simply won't match the route.
You can make params optional like:
app.get('/nachos/:x?/:cheese?/:tomatoes?/:salsa?/:hotsauce?', (req, res) => {
or add routes to match, which could get out of hand.
app.get([
//...
'/nachos/:x/:cheese/:tomatoes',
'/nachos/:x/:cheese/:tomatoes/:hotsauce',
'/nachos/:x/:cheese/:tomatoes/:salsa/:hotsauce',
//...
], (req, res) => {
You don't really do optional arguments in a route definition that looks like this:
/nachos/:x/:cheese/:tomatoes/:salsa/:hotsauce
because in order for the route to match, every one of the parameters must be present and for req.params to contain the right option, they must all be in the correct order. If these are variations, some of which are entirely optional, then matching them the way you were is just not the proper URL design and matching a varying URL like that in Express will be a bit of a pain.
The simplest way I can think of is to just put the optional ingredients in a query string as in:
/nachos/2?cheese=yes&tomatoes=yes&salsa=yes&hotsauce=yes
Then, you just match the route: /nachos/:x as the only required options for the URL and everything else can be optionally specified in the querystring and you can write your code so that it defaults to "no" if the option is not present. So, an order without hotsauce could be either of these:
/nachos/2?cheese=yes&tomatoes=yes&salsa=yes&hotsauce=no
/nachos/2?cheese=yes&tomatoes=yes&salsa=yes
An order without hotsauce or salsa could just be this:
/nachos/2?cheese=yes&tomatoes=yes
Then, your request handler would look like this:
const orderOptions = ["cheese", "tomatoes", "salsa", "hotsauce"];
app.get('/nachos/:x', (req, res) => {
console.log(req.query);
let text = orderOptions.map(item => {
return req.query[item] === "yes" ? item : null;
}).filter(item => !!item).join(", ");
res.send(`You ordered ${req.params.x} nacho(s) with ${text}.`);
});
I should mention that if this request is actually specifying an order, then it should probably be a POST, not a GET and the options should be in the body of the POST and they would take the same form as the querystring, probably encoded just like application/x-www-form-urlencoded from form POSTs.
Passing parameters this way request to the API user to send the parameters in the correct order. To handle the case you want (an ingredient missing), you would need to create another route to handle it. But you can do this in another way, like passing the parameters as query strings or even sending them on the request body (for non-GET routers preferably).

axios didn't return data with matching query string of parameter object but returns all the data in vanila JS

i have an api endpoint https://countriesnode.herokuapp.com/v1/countries.
Now i am fetching all the countries by
axios.get('https://countriesnode.herokuapp.com/v1/countries')
it returns successfully. Besides I want to fetch single countries with the country code like 'BB' .and i am trying with params and my object is like below
axios.get('https://countriesnode.herokuapp.com/v1/countries',
{
params: {
code: codeId
}
but it returns all the data like above rather than showing a single country with the following code. I also want to extract only the currency and area code. I wanted to try like this, don't know it gonna work or not.
.then(axios.spread((object) => {
console.log('Currency: ', object.data.currency);
console.log('Area code: ', object.data.emojiU);
}));
please someone help me... It took me almose the hole day for this but not able to success.
As per your comment, if you want to get the data of a specific country, you only have to append the country code id to the URL:
const codeId = 'BB';
axios.get(`https://countriesnode.herokuapp.com/v1/countries/${codeId}`)
Would give you the data for Barbados.
If you want to access the currency attribute you can do so with the code:
const codeId = 'BB';
axios.get(`https://countriesnode.herokuapp.com/v1/countries/${codeId}`).then(function(response) {
const currency = response.data.currency;
});

Fetch Api get params

I am trying to make a "GET" request using window.fetch, and I need to pass in a param which takes in an entire array as the value. For example, the request url should look like this
'https://someapi/production?moves=[]'
I have the following segment, which ends up in a 400 request, because the array gets evaluated to empty
let url = new URL('https://someapi/production');
let params = {moves: []};
Object.keys(params).forEach(key => url.searchParams.append(key, params[key]));
console.log(url);
fetch(url.href)
.then(res => res.json())
.then(val => {
console.log(val);
});
Upon inspecting the url.href looks like
https://someapi/production?moves=
where as I want it to be
https://someapi/production?moves=[]
Any suggestions on how I can achieve this?
Because the second argument of url.searchParams.append(key, params[key]) is not a string, URLSearchParams.append will result in the value being stringified. I assume that's by calling the Array.prototype.toString() method on it, which omits the array brackets.
So, you'll either need to concatenate some brackets onto that string, or call a different method (like JSON.stringify mentioned in the comments) to keep the brackets.

Categories

Resources