Reflect and make Axios request in the browser's URL - javascript

What I'm looking for
Bit of JavaScript logic help; although, I am not sure what I will need to do via Vue Router. Not looking exactly for the answer, but more pointed in the right direction (I'm not even sure I'm phrasing this question correctly).
Problem
I have been making API requests with Axios (no problem there). I have a JWT token in the requests’ headers. However, (never done this before) I now need to have the search params the user entered in the browser’s URL when they make a request to share the link to their coworkers which will route to the same page with the same options entered/selected and the API request called with those query params.
What I really don’t know is:
A. What’s the best way to make an API request on route (loading the url with query params)? The route of the page does NOT match the corresponding API endpoint Url.
B. How do I get the users’ entered/selected data into the browser’s URL?
C. Do I need to modify my route objects for those pages to still route correctly even if there is now a query string?
Solution
(Must be purely a frontend solution - I’m using the whole vue ecosystem)

Figured out what I need to do:
A
The project is not server-side rendered; therefore, I need to parse the URL on Vue's created and make a request with the params in the query string. This will seem like the URL caused a API request.
B
Simply append Axios' request query string to the URL, which I believe is cosmetic and should be fine.
C
I'm not sure, but will play around with it.

Related

Can you use a POST to GET data?

A company is asking me to do an Angular assignment. They provide the following instructions, but the API URL doesn't work:
Create a single page angular application and use the following API to retrieve sports results and sort into a table of results that are displayed. Each sport result contains several data and always includes the publication time.
Method: POST
Content-Type: application/json
Url: https://ancient-wood-1161.getsandbox.com:443/results
Tasks:
-Display the sports results in reverse chronological order on the page.
-Add a filter to the page to display only certain types or events (e.g. f1Results)
-How can you confirm the code works?
-Bonus: Implement the rest call asynchronously
You can click the URL https://ancient-wood-1161.getsandbox.com:443/results right now and see that it doesn't work - it returns {"errors":[{"message":"Error processing request"}]} and in Angular it gives me a standard CORS error.
I asked the company to please send a working URL and/or update the API to accept requests from everywhere. Their response was:
*guy's name* confirmed it worked. It is a post and the content type is json.
Can you use a POST request to GET data?
Absolutely. Take for example your avg Login Request that returns an access token for instance. It is going to be a POST as POST also has a bit more security than GET given that the payload is in the body rather than the URL string.
As for their excuse of it not working, try it in postman and see if the same issue still occurs. If it still does then ask them where did they test their API as if it is on prem then no duh the CORS would work. It is most likely not a company you would want to work for.
Yes, you can. On some cases it may be necessary, since GET doesn't take a body while POST does. So it can get you around things like URL length limits.

How to map a custom URL to a REST resource in an SPA?

I have a design issue with my SPA, and hope someone can give me some direction. A user profile page is rendered like this:
The browser fetches /some-username.
The server checks to see if the request was a XMLHTTPRequest or not. It is not, and so it simply returns the bundled javascript app to the browser to execute.
The javascript bundle is executed in the browser, it sees the current URL and makes an AJAX request, again to /some-username.
The server sees the XMLHTTPRequest header, looks up the user who has the custom URL "/some-username" and returns the JSON data about the user back to the javascript to render.
This feels wrong. The app should be making RESTful requests to /users/:id to fetch the user data. But how can it know the id that corresponds to the user with the URL /some-username?
It is worth adding an extra HTTP request just to look up the resource identifier? Something like /get_user_id?url=/some-username.
Are you flexible about your API? If so you may change /some-username to /user-id or if you want to include username /user-id/username but ignore username.
As alternative it is also common to make requests in a filter form. Like /users?username=peter
And feel free to use /users/peter if your username identifies the user. Becuase it's actualy the id (that doesn't have to be integer) and then your url is exactly /users/:id
There is nothing "unRESTful" about /some-username. It's just another resource. The response - I hope - contains the canonical URL /user/id anyway, either as a header or as some kind of "self" link.
That's also how you could achieve your goal. Embed the URL in the page either as JavaScript or as a header equivalent (unfortunately you cannot read the headers of the page request with JavaScript):
//header. Can also use a custom header like X-User-Location
<meta http-eqiv="Location" content="/user/id">
//JavaScript
<script>
var userURL = '/user/id
</script>
I recommend keeping your current approach.

Getting backbone routing to work with pushstate and node.js/express as server

I'm trying to build a single page app with backbone.js on front end and node.js/express as server, I want to have a base HTML file for the root, and then when user navigates to any path such as
mydomain.com/foo/bar
I want to be able to handle that path on the client side by javascript instead of making a round trip to server. I am reading about backbone routing and HTML5 push state. In this article he describes push state like this,
In fact, PushState is really nothing more than a standard API for JavaScript, that allows us to manipulate the browser history by “push”ing full URLs into the browser’s URL without making a round trip to the server, and respond to changes in the URL with Javascript – all without the use of URL hash fragments.
but when I use push state it does actually makes a server request and expects server to deliver contents under /foo/bar . I don't understand how I can avoid that.
Now let's assume that even with push state, your client is going to make a server request under mydomain.com/foo/bar when you visit this URL directly. In that case, since I'm serving the default HTML file, and this default HTML file has links to scripts in it:
<script type="text/javascript" src="/scripts/myscript.js" ></script>
When this HTML loads, it starts looking for scripts under /foo directory instead of root since the server was requested under /foo which obviously does not exist. How do I fix this?
I'm really confused at this point. I'd like to know how URL routing is usually done in a single page application. Any help will be greatly appreciated. You can also refer to this other question I have posted about the same issue: Backbone Router : Get rid of # in the URL
The solution you're trying to implement is very interesting but not that simple. When your server gets a request to mydomain.com/foo/bar, you should redirect to your root with some parameter that the frontend (JavaScript) app can pick-up to know what the original request was for. For example:
Client sends GET http://mydomain.com/foo/bar
Server redirects (responds 302 with Location header set) to http://mydomain.com/#!/foo/bar
Your SPA is loaded in the browser, and on startup you check for the hash and find #!/foo/bar, so you remove the hash and trigger the /foo/bar route (that's a push-state). Your resulting URL is again http://mydomain.com/foo/bar: the original URL the user browsed to.
Grooveshark does something similar to this, though it actually responds with a page to the request sent in 1., which does the hash replacement in the client and then sends another request to the server. It looks unnecessary to me, maybe I'm overlooking something.

how to use JavaScript to sniff url header

the url is input by end users as string on my page, so may point to any domains.
JavaScript in current page needs to sniff the url, verify whether it's still valid, and return the types as image, or video, or audio, even considering html5 video audio tag and existent flash embed. And No need to wait for the complete file transfer.
Can someone help, from concept? thanks very much.
i'm aware the cross domain problem on ajax. So no idea on basic how-to.
If what you're asking, is:
Given any URL -> lookup given URL using a javascript ajax request, and determine if it is a video/audio/image - then, once detected, use the URL accordingly, then you can do something like this:
jQuery and AJAX response header
However, you'll not be able to make a request using client-side JavaScript to another domain, as it will require a cross-domain request (where your alternatives are JsonP, or weird headers in the response).
You're better off passing the URL to your own server, and performing the logic there (Via some kind of server-side web request) and passing a payload back to the client, with the required information in JSON or something - e.g.
{payload: 'video'}
Old question, but I recently wrote a utility that might help you out. It's a CORS-enabled MIME-type checker. See the API doc at lecoq.herokuapp.com
Use it like so: example

How to prevent direct access to my JSON service?

I have a JSON web service to return home markers to be displayed on my Google Map.
Essentially, http://example.com calls the web service to find out the location of all map markers to display like so:
http://example.com/json/?zipcode=12345
And it returns a JSON string such as:
{"address": "321 Main St, Mountain View, CA, USA", ...}
So on my index.html page, I take that JSON string and place the map markers.
However, what I don't want to have happen is people calling out to my JSON web service directly.
I only want http://example.com/index.html to be able to call my http://example.com/json/ web service ... and not some random dude calling the /json/ directly.
Quesiton: how do I prevent direct calling/access to my http://example.com/json/ web service?
UPDATE:
To give more clarity, http://example.com/index.html call http://example.com/json/?zipcode=12345 ... and the JSON service
- returns semi-sensitive data,
- returns a JSON array,
- responds to GET requests,
- the browser making the request has JavaScript enabled
Again, what I don't want to have happen is people simply look at my index.html source code and then call the JSON service directly.
There are a few good ways to authenticate clients.
By IP address. In Apache, use the Allow / Deny directives.
By HTTP auth: basic or digest. This is nice and standardized, and uses usernames/passwords to authenticate.
By cookie. You'll have to come up with the cookie.
By a custom HTTP header that you invent.
Edit:
I didn't catch at first that your web service is being called by client-side code. It is literally NOT POSSIBLE to prevent people from calling your web service directly, if you let client-side Javascript do it. Someone could just read the source code.
Some more specific answers here, but I'd like to make the following general point:
Anything done over AJAX is being loaded by the user's browser. You could make a hacker's life hard if you wanted to, but, ultimately, there is no way of stopping me from getting data that you already freely make available to me. Any service that is publicly available is publicly available, plain and simple.
If you are using Apache you can set allow/deny on locations.
http://www.apachesecurity.net/
or here is a link to the apache docs on the Deny directive
http://httpd.apache.org/docs/2.0/mod/mod_access.html#deny
EDITS (responding to the new info).
The Deny directive also works with environment variables. You can restrict access based on browser string (not really secure, but discourages casual browsing) which would still allow XHR calls.
I would suggest the best way to accomplish this is to have a token of some kind that validates the request is a 'good' request. You can do that with a cookie, a session store of some kind, or a parameter (or some combination).
What I would suggest for something like this is to generate a unique url for the service that expires after a short period of time. You could do something like this pretty easily with Memcache. This strategy could also be used to obfuscate the service url (which would not provide any actual security, but would raise the bar for someone wanting to make direct calls).
Lastly, you could also use public key crypto to do this, but that would be very heavy. You would need to generate a new pub/priv key pair for each request and return the pubkey to the js client (here is a link to an implementation in javascript) http://www.cs.pitt.edu/~kirk/cs1501/notes/rsademo/
You can add a random number as a flag to determine whether the request are coming from the page just sent:
1) When generates index.html, add a random number to the JSON request URL:
Old: http://example.com/json/?zipcode=12345
New: http://example.com/json/?zipcode=12345&f=234234234234234234
Add this number to the Session Context as well.
2) The client browser renders the index.html and request JSON data by the new URL.
3) Your server gets the json request and checks the flag number with Session Context. If matched, response data. Otherwise, return an error message.
4) Clear Session Context by the end of response, or timeout triggered.
Accept only POST requests to the JSON-yielding URL. That won't prevent determined people from getting to it, but it will prevent casual browsing.
I know this is old but for anyone getting here later this is the easiest way to do this. You need to protect the AJAX subpage with a password that you can set on the container page before calling the include.
The easiest way to do this is to require HTTPS on the AJAX call and pass a POST variable. HTTPS + POST ensures the password is always encrypted.
So on the AJAX/sub-page do something like
if ($_POST["access"] == "makeupapassword")
{
...
}
else
{
echo "You can't access this directly";
}
When you call the AJAX make sure to include the POST variable and password in your payload. Since it is in POST it will be encrypted, and since it is random (hopefully) nobody will be able to guess it.
If you want to include or require the PHP directly on another page, just set the POST variable to the password before including it.
$_POST["access"] = "makeupapassword";
require("path/to/the/ajax/file.php");
This is a lot better than maintaining a global variable, session variable, or cookie because some of those are persistent across page loads so you have to make sure to reset the state after checking so users can't get accidental access.
Also I think it is better than page headers because it can't be sniffed since it is secured by HHTPS.
You'll probably have to have some kind of cookie-based authentication. In addition, Ignacio has a good point about using POST. This can help prevent JSON hijacking if you have untrusted scripts running on your domain. However, I don't think using POST is strictly necessary unless the outermost JSON type is an array. In your example it is an object.

Categories

Resources