Query string with fetch javascript - javascript

I'm working on a project and i want to define url object that will be passed to fetch ex.
https://t1.testing.com/test/api/v1/blog?pagingindex=0&pagingresults=10
const url_object = {
url: `https://t1.testing.com/test/api/v1/blog`,
url_params: {
method: "POST",
pagingindex: 0,
pagingresults: 10
}
};
and when i call fetch(url_object.url, url_object.url_params) i get an error. How can i incorporate this into fetch? So i need to allow user to define method and query string that will be passed. Thanks in advance!

You can have your cake and eat it too -- easily convert dictionary style objects to query parameters with no fuss:
var url = new URL('https://example.com/');
url.search = new URLSearchParams({blah: 'lalala', rawr: 'arwrar'});
console.log(url.toString()); // https://example.com/?blah=lalala&rawr=arwrar

The object you have labeled url_params is described by the MDN documentation as:
An options object containing any custom settings that you want to apply to the request.
It then goes on to list the properties you can include there.
pagingindex and pagingresults are not among them.
The query string is part of the URL. If you want to put data there, then put it in the URL.
const url_object = {
url: `https://t1.testing.com/test/api/v1/blog?pagingindex=0&pagingresults=10`,
url_params: {
method: "POST"
}
};
You may wish to use the URL object to construct the URL (it will handle escaping for you).

Related

Send unencoded query parameters in Ember

I'm working with an API that only accepts unencoded query parameters. I notice that when I make a query in Ember like so:
this.store.query('listing', {filter: params});
The uri is encoded when it hits the api:
/v1/listing?filter%5Bcategory%5D=123
What I need is for the query parameters to get to my API unencoded, eg:
/v1/listing?filter[category]=123
Can anybody give me a steer on what is the right way to do this in Ember?
So the solution I ended up implementing is not great but it does the trick until I find a better way.
Ember uses Ajax to form the request, so what I did was override 'query' in my JSONAPIAdapter to pass through a custom set of options. My query now looks like this:
query(store, type, query) {
let url = this.buildURL(type.modelName, null, null, 'query', query);
if (this.sortQueryParams) {
query = this.sortQueryParams(query);
}
query = decodeURI(Ember.$.param(query));
let options = {
"processData": false,
"data": query
};
return this.ajax(url, 'GET', options);
},
The key was to stop ajax's automatic processing of the data object, and decode the result of jquery's 'param()' helper function, which is used to convert the query param object into a serialized string.
The result is a decoded query param string like so:
/v1/listing?filter[category]=123

How to get to request parameters in Postman?

I'm writing tests for Postman which in general works pretty easily. However, I now want to access some of the data of the request, a query parameter to be exact.
You can access the request URL through the "request.url" object which returns a String. Is there an easy way in Postman to parse this URL string to access the query parameter(s)?
The pm.request.url.query.all() array holds all query params as objects.
To get the parameters as a dictionary you can use:
var query = {};
pm.request.url.query.all().forEach((param) => { query[param.key] = param.value});
I have been looking to access the request params for writing tests (in POSTMAN). I ended up parsing the request.url which is available in POSTMAN.
const paramsString = request.url.split('?')[1];
const eachParamArray = paramsString.split('&');
let params = {};
eachParamArray.forEach((param) => {
const key = param.split('=')[0];
const value = param.split('=')[1];
Object.assign(params, {[key]: value});
});
console.log(params); // this is object with request params as key value pairs
edit: Added Github Gist
If you want to extract the query string in URL encoded format without parsing it. Here is how to do it:
pm.request.url.getQueryString() // example output: foo=1&bar=2&baz=3
pm.request.url.query returns PropertyList of QueryParam objects. You can get one parameter pm.request.url.query.get() or all pm.request.url.query.all() for example. See PropertyList methods.
It's pretty simple - to access YOUR_PARAM value use
pm.request.url.query.toObject().YOUR_PARAM
Below one for postman 8.7 & up
var ref = pm.request.url.query.get('your-param-name');
I don't think there's any out of box property available in Postman request object for query parameter(s).
Currently four properties are associated with 'Request' object:
data {object} - this is a dictionary of form data for the request. (request.data[“key”]==”value”) headers {object} - this is a dictionary of headers for the request (request.headers[“key”]==”value”) method {string} - GET/POST/PUT etc.
url {string} - the url for the request.
Source: https://www.getpostman.com/docs/sandbox
Bit late to the party here, but I've been using the following to get an array of url query params, looping over them and building a key/value pair with those that are
// the message is made up of the order/filter etc params
// params need to be put into alphabetical order
var current_message = '';
var query_params = postman.__execution.request.url.query;
var struct_params = {};
// make a simple struct of key/value pairs
query_params.each(function(param){
// check if the key is not disabled
if( !param.disabled ) {
struct_params[ param.key ] = param.value;
}
});
so if my url is example.com then the array is empty and the structure has nothing, {}
if the url is example.com?foo=bar then the array contains
{
description: {},
disabled:false
key:"foo"
value:"bar"
}
and my structure ends up being { foo: 'bar' }
Toggling the checkbox next to the property updates the disabled property:
have a look in the console doing :
console.log(request);
it'll show you all you can get from request. Then you shall access the different parameters using request., ie. request.name if you want the test name.
If you want a particular element in the url, I'm afraid you'll have to use some coding to obtain it (sorry I'm a beginner in javascript)
Hope this helps
Alexandre
Older post, but I've gotten this to work:
For some reason the debugger sees pm.request.url.query as an array with the items you want, but as soon as you try to get an item from it, its always null. I.e. pm.request.url.query[0] (or .get(0)) will return null, despite the debugger showing it has something at 0.
I have no idea why, but for some reason, it is not at index 0, despite the debugger claiming it is. Instead, you need to filter the query first. Such as this:
var getParamFromQuery = function (key)
{
var x = pm.request.url.query;
var newArr = x.filter(function(item){
return item != null && item.key == key;
});
return newArr[0];
};
var getValueFromQuery = function (key)
{
return getParamFromQuery(key).value;
};
var paxid = getValueFromQuery("paxid");
getParamFromQuery returns the parameter with the fields for key, value and disabled. getValueFromQuery returns just the value.

How do I retrieve a list of posts based on a tag slug in WP Rest API V2?

I have an application that retrieves data from a Wordpress site using the WP Rest API V2. The API has recently been change from using a 'filter[tag]=' to a new syntax. I am looking to retrieve a list of posts within a specific tag.
Old syntax:
http://demo.wp-api.org/wp-json/wp/v2/posts?filter[tag]=slug
The new syntax looks like this:
http://demo.wp-api.org/wp-json/wp/v2/posts?tags=id
It now takes an ID integer instead of a slug as argument. I have looked over the documentation but I can't seem to find a solution for this. I have no option of using the id, I can only use the slug!
The WP Rest API documentation can be found here: https://developer.wordpress.org/rest-api/reference/posts/
Do you have any idea how to solve this?
Just get the list of tags by calling http://demo.wp-api.org/wp-json/wp/v2/tags before your requesting posts on a specifiy tagId. In that way you will find the tagId you need by filtering the data by your "slug". The demo API is not support CORS thats way I dont create a working fiddle.
Nested $http request bad example
$http({
method: 'GET',
url: 'http://demo.wp-api.org/wp-json/wp/v2/tags'
}).then(function (result) {
var filtered = filterFilter(result.data, { slug: 'dolor'});
$http({
method: 'GET',
url: 'http://demo.wp-api.org/wp-json/wp/v2/posts?tags=' + filtered[0].id
}).then(function (result) {
console.log(result.data);
});
});
Looking at the official API docs for TAGS, you can search for strings in the tags schema with a request like this:
http://demo.wp-api.org/wp-json/wp/v2/tags?search=yourslug
The resulting JSON output will display tags containing the string you searched in any of the schema fields, like slug.
After you retrieved the desired tag, you can fetch the posts with that specific tag using it's ID (as suggested by #lin).

Ember data - One model, two endpoints

In ember data, if you want to fetch the collection of a model, it's convention to use this:
this.store.findAll('order');
or with a filter, this:
this.store.find('order', {shopId: 63});
So you pass the model name, and Ember-data will build the URL for you, which would look something like (depending on your adapter):
GET /api/orders
GET /api/orders?shopId=63
So this does two things
Build the URL to fetch data from the api
Map the collection as JavaScript objects, using the model that you passed as 1st argument
But what if I want to fetch orders from two URLs; /api/orders and /api/new_orders ?
The first one will work as usual: this.store.findAll('order'), but is there a way to override the api path that you fetch from?
Maybe something like this.store.find('order', {path: '/new_orders'})?
So that I can end up with a collection of objects modelled with my order model, but fetched from a different route
You need to have a rest adapter for this store and override the findAll method. The default implementation is as such
findAll: function(store, type, sinceToken) {
var query, url;
if (sinceToken) {
query = { since: sinceToken };
}
url = this.buildURL(type.modelName, null, null, 'findAll');
return this.ajax(url, 'GET', { data: query });
}
buildUrl will return a proper endpoint for your first url. you could then parse this url and modify it to make a second request with the same data, but with to your second endpoint. Than you could merge the responses or use them separately.
Reference: https://github.com/emberjs/data/blob/v1.13.5/packages/ember-data/lib/adapters/rest-adapter.js#L398

backbone.js change url parameter of a Model and fetch does not update data fetched

I have the following Model:
window.MyModel = Backbone.Model.extend({
initialize: function(props){
this.url = props.url;
}
parse: function(){
// #override- parsing data fetched from URL
}
});
// instantiate
var mod = new MyModel({url: 'some/url/here'});
I use this global variable 'mod' to fetch some data into this model from backend.
// fetch
mod.fetch({
success: function(){ ...},
error: ...
});
All above works well....
My Issue: I want to reuse this model by changing resetting the url and call fetch but it does not update the url somehow. I have tried the following:
mod.fetch({
data: {url:'/some/other/url'},
postData: true,
success: function(){ //process data},
error: ...
});
mod.set({url: '/some/other/url'});
// called fetch() without data: and postData: attributes as mentioned in previous
How do I set the url for my model so that I could call fetch() and it fetches data from updated url? Am I missing something. Thanks for any pointers..
UPDATE 1: Basically, I am unable to get updated values if I did
model.set({url: 'new value'});
followed by
model.fetch();
'model' is a global variable. Creating a fresh instance of 'model' works:
model = new Model({url:'/some/other/url'});
model.fetch();
however, works as required. Does this mean that a model instance is permanently attached to a url and it cannot be reset?
ANSWER TO MY QUESTION in UPDATE 1 Model instance is not permanently attached to a url. It can be reset dynamically. Please read through #tkone's thorough explanation and then #fguillens' solution for a better understanding.
After have understood the #tkone 's explanation...
If you still want to have a dynamic Model.url you always can delay its construction to run time, try this:
window.MyModel = Backbone.Model.extend({
url: function(){
return this.instanceUrl;
},
initialize: function(props){
this.instanceUrl = props.url;
}
}
Well the answer here is that you want to do:
mod.url = '/some/other/url'
The URL isn't part of the instance of the model itself, but rather an attribute of the MyModel object that you're creating your model instance from. Therefore, you'd just set it like it was an normal JavaScript object property. set is used only when the data you're setting (or conversely getting with get) is actually an attribute of the data you want to send/receive from the server.
But why you're changing the URL is the question we should be asking. The idea behind Backbone's model/collection system is that you speak to a REST endpoint and each model has a corresponding endpoint.
Like you've got a blog and that blog has an "entry" object which is available at:
/rest/entry/
And you've got a Backbone model for Entry:
Entry = Backbone.Model.extend({urlBase: '/rest/entry'});
Now when you save or fetch Backbone knows how this works.
So like you're making a new model:
e = new Entry();
e.set({title: "my blog rulez", body: "this is the best blog evar!!!!1!!"});
e.save();
This would then make Backbone do an HTTP POST request to /rest/entry with the body:
{
"title": "my blog rulez",
"body": "this is the best blog evar!!!!1!!"
}
(When you do your mod.set({url: '/some/other/url'}); you're actually adding a field called url to the dataset, so the server would send "url": "/some/other/url" as part of that JSON POST body above:
{
"title": "my blog rulez",
"body": "this is the best blog evar!!!!1!!",
"url": "/some/other/url"
}
The server would then respond with an HTTP 200 (or 201) response with the same model, only with, like, say, and ID attached:
{
"id": 1,
"title": "my blog rulez",
"body": "this is the best blog evar!!!!1!!"
}
And that's not what you're looking for, right?)
Now you've got this model and it's got an ID. This means if you change it:
e.set('title', 'my blog is actually just ok');
e.save()
Backbone now makes an HTTP PUT request on /rest/entry/1 to update the resource on the server.
The server sees that you're talking about ID 1 on the /rest/entry/ endpoint, so knows to update an existing record (and send back an HTTP 200).
TL;DR
Don't change the URL, Backbone will. Make a new model for a new piece of data.
model.urlRoot = "/your/url"
OR
model.urlRoot = function(){ return "/your/url"; }
OR
model.url = "/your/url"
OR
model.url = function(){ return "/your/url"; }
Default 'url' property of a Backbone.Model object is as below. Backbone.js doc says:
Default URL for the model's representation on the server -- if you're using Backbone's restful methods, override this to change the endpoint that will be called.
url: function() {
var base = getValue(this, 'urlRoot') || getValue(this.collection, 'url') || urlError();
if (this.isNew()) return base;
return base + (base.charAt(base.length - 1) == '/' ? '' : '/') + encodeURIComponent(this.id);
},
Clearly, It first gets the value of urlRoot, if not available, it will look at the url of the collection to which model belongs. By defining urlRoot instead of url has an advantage of falling back to collection url in case urlRoot is null.
You can set url as option in fetch function, like this:
var mod = new MyModel();
mod.fetch({
url: '/some/other/url',
data: {}
});

Categories

Resources