Could anyone share some guidance into how to cache a call in the browser and have it last 5 minutes, 30 seconds, really anytime at all?
I'm having some real difficulties with this.
This works but can't figure out how to make it expire
fetch(
'/get/id',
{
method: 'GET',
headers: { 'Content-Type': 'application/json' },
cache: 'force-cache'
}
);
This doesn't work at all
fetch(
'/get/id',
{
method: 'GET',
headers: { 'Content-Type': 'application/json', 'Cache-Control': 'max-age=30' },
}
);
Cache-Control is an HTTP cache header comprised of a set of directives that allow you to define when/how a response should be cached and for how long. You can configure your server to attach the Cache-Control header in the response, specifying which directives to use.
For this cache control to need to update the server to include the cache control in response, like below where the server specifies the cache control type (public) and max age of the response for the client.
Other option, is to implement your own caching mechanism on client side, which expires in 5 min.
Below is the code which implements the cache fetch call with the session storage as cache storage and 5 min expiry, invalidates itself if stale.
https://github.com/abhishekasana/jsDevelopCell/blob/master/cached_fetch.js
Related
let's assume that there is a website under HTTPS, in that WebSite the user can set the IP of a local machine (thermal printer in this case). How can the user print something on that printer by using the website from his device?
The user have to use the WebSite only under the local network where the thermal printer is to be able to print.
The printer has a http server in it which it uses for the communication.
At this point how can a HTTPS website send a HTTP request to that local thermal printer?
Assuming you want this to be a variable that any user inputs,and that any user on any network has the ability to access their own printer, you would need it to be executed on the frontend. This way each user will be able to access the printer on their own network.
That gives you basically one option. Javascript. So if you wanted a stored request with some variables, you could have the javascript store variable from the DOM and then post a fetch request https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
Here is an example function
// Example POST method implementation:
async function postData(url = '', data = {}) {
// Default options are marked with *
const response = await fetch(url, {
method: 'POST', // *GET, POST, PUT, DELETE, etc.
mode: 'cors', // no-cors, *cors, same-origin
cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
credentials: 'same-origin', // include, *same-origin, omit
headers: {
'Content-Type': 'application/json'
// 'Content-Type': 'application/x-www-form-urlencoded',
},
redirect: 'follow', // manual, *follow, error
referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
body: JSON.stringify(data) // body data type must match "Content-Type" header
});
return response.json(); // parses JSON response into native JavaScript objects
}
postData('https://example.com/answer', { answer: 42 })
.then(data => {
console.log(data); // JSON data parsed by `data.json()` call
});
You are likely struggling because of CORS.
You can find in depth discussion here https://javascript.info/fetch-crossorigin
In short, you will need to modify the fetch headers to have the correct credentials, mode, etc. as seen in the comments in the above snippet.
We are hitting rate limiting issues with Graph APIs usage. Is there any way to upgrade our tenant/membership to improve the performance and response times?
It takes up to minutes, and sometimes APIs not getting processed at all. We require real time response.
Any pointers in this regard will be really helpful.
Thanks
Laksh
Request Type : Get Channel messages API using Global Admin credentials is called with 1Second interval
Request URL : GET https://graph.microsoft.com/beta/teams/${teamId}/channels/${channelId}/messages
const options = {
headers: {
Authorization: `Bearer ${globalAdminAccessToken}`,
‘Content-Type': 'application/json',
Accept: '*/*'
}
};
let url = `https://graph.microsoft.com/beta/teams/${teamId}/channels/${channelId}/messages`;
axios
.get(
url,
options
)
.then(resp => {
console.log(resp);
})
.catch(error => {
console.log(error);
});
I have two domains:
https://localhost.com # SPA served via Nginx
https://api.localhost.com # Flask API proxied by nginx (uwsgi_pass)
and added both to my hosts file via 127.0.0.1 localhost.com api.localhost.com.
I've added server-side oauth2 via GitHub's oauth service and I'm able to authenticate (I receive an access token and can query the GitHub API). This is the "flow":
user calls: https://localhost.com
ajax: https://api.localhost.com/v1/login # gets the app's Github OAuth url
# sets a session cookie for
# localhost.com
user calls: https://github.com/... # gets redirected to log in ect.
redirect: https://api.localhost.com/callback
# github redirects to the callback
# can access some session cookie
# (I assume) from localhost.com
redirect: https://localhost.com # now has two session cookies:
# localhost.com
# api.localhost.com
ajax: https://api.localhost.com/v1/username
# this is where it breaks
I set both, the server-side CORS headers for api.localhost.com (snippet from nginx.conf)
add_header 'Access-Control-Allow-Origin' "https://localhost.com";
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Content-Type, *';
and the withCredentials parameter in the queries:
$.getJSON("https://api.localhost.com/v1/login",
{
xhrFields: { withCredentials: true },
},
(response) => {
this.login_url = response;
});
$.getJSON("https://api.localhost.com/v1/username",
{
xhrFields: { withCredentials: true },
},
(response) => {
console.log(response)
this.username = response;
});
The first cross-domain ajax: https://api.localhost.com/v1/login works and sets a cookie, so I think it's configured correctly. (I might be wrong.)
However, the second ajax: https://api.localhost.com/v1/username doesn't seem to send the session cookie, as I am left with an empty session in flask:
from flask import session
# [ ... ]
def username_get():
return str(list(session.keys())) # returns "[]"
I can manually decrypt both session cookies (localhost.com and api.localhost.com). They both have the same content (username, access token and oauth_state [required during GitHub OAuth]) and indicate that authentication was successful.
What I don't understand is:
Why do I get two cookies, in particular why is the session cookie from ajax: https://api.localhost.com/v1/login stored in localhost.com and not api.localhost.com?
Github OAuth is working, meaning redirect: https://api.localhost.com/callback receives the session cookie set by https://api.localhost.com/v1/login and can use the data (oauth_state). However the subsequent ajax: https://api.localhost.com/v1/Username does not send the session cookie. Why?
I hope I've included all the necessary bits. This is a very puzzling problem and none of the existing SO questions helped me past this point. ANY help or pointers are highly appreciated.
(2) I was using $.getJSON wrong. It's so simple that it hurts.
As per the documentation:
jQuery.getJSON( url [, data ] [, success ] )
and data will be appended to the URL as a query parameter. Thus replacing the call with
$.ajax({
dataType: "json",
url: "https://api.localhost.com/v1/username",
xhrFields: { withCredentials: true },
success: (response) =>
{
this.username = response;
}
});
(not using the shorthand) sets the appropriate xhrField and now correctly sends the cookie.
(1) Probably caused by caching or some temporary files. I brought down the entire server, cleared all temp files and did the same with my browser (Chrome). After restarting, I only get a single session cookie for api.localhost.com which is the expected behavior.
I'm making a client-side request out to V2 of the Square API using Vue and Axios. My Vue component is as follows:
import axios from 'axios';
export default {
mounted() {
var instance = axios.create({
baseURL: 'https://connect.squareup.com/v2/',
timeout: 1000,
headers: {
'Authorization': 'Bearer xxxxxxxxxxxxxxxxx',
'Accepts': 'application/json',
'Content-Type': 'application/json'
}
});
instance.get('catalog/list')
.then(function (response) {
console.log(response);
}) ;
}
}
However, when I make that call, I receive the following error:
Failed to load https://connect.squareup.com/v2/catalog/list: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://local-env.dev' is therefore not allowed access. The response had HTTP status code 403.
That error suggests that there is some configuration that has to happen on the Square side, but I saw no opportunity to whitelist domains, etc.
Has anyone come across this error before, regardless of service, and if so, how did you resolve?
I don't think the Square API supports being called from a browser. I used Postman to do an OPTIONS request on https://connect.squareup.com/v2/catalog/list and the response was a NOT_FOUND. The OPTIONS request is needed for proper CORS support.
Plus, if you did this, I would think your auth token would need to be sent to the client -- thus exposing it to everyone. It looks like the Square API is only designed to be called from a server. But that is just based on me skimming the docs a bit. I have no experience using their API.
When doing OAuth authorization request you are not supposed to do it from your application. Create and URL with the parameters and open it in a new browser window or tab, Something like:
const grants='MERCHANT_PROFILE_READ CUSTOMERS_READ CUSTOMERS_WRITE PAYMENTS_READ PAYMENTS_WRITE PAYMENTS_WRITE_ADDITIONAL_RECIPIENTS PAYMENTS_WRITE_IN_PERSON';
const params = new HttpParams()
.set('scope', grants)
.set('client_id', <YourSquareApplicationId>)
.set('state', '1878789');
const requestUrl = `${<squareUrl>}/oauth2/authorize?${params.toString()}`;
window.open(requestUrl, "_blank");
That new window is supposed to ask the end user to login to his account and accept or deny the request.
Is it possible to enable date field in to http requests? I have an object on my client side:
let init = {
method: typeof method === 'string' ? method : 'GET',
headers: {
'Content-Type': 'application/json; charset=utf-8',
'Accept': 'application/json',
'Accept-Language': getLanguage()
}
The problem is I adding 'Date' : new Date() to the header server doesn't get any key-value pair (via WebApi). Also in network section of browser there is no above field. I've read some information this field is closed for any manipulation. As I understand I need to enable it for including not by hands. So, how can I tell to browser to send it?
Unfortunately, that's not possible once the browser is supposed to set the header, not you. If you were able to set the header, that would defeat the purpose of the security feature.
Also, if you try to force it you'll probably get the error:
Refused to set unsafe header "Date"
Once we try the request without setting this header, we'll see that the browser doesn't set it for you (only for response object, which is easier to manipulate).
Some alternatives:
Create custom headers and receive their values at the WebApi
Or even pass the value as a parameter (body POST, e.g)