axios cancelled requests still showing in ngrok - react-native

I'm using ngrok to expose my local webserver to the internet. In the terminal window for ngrok, you can see a list of the HTTP requests.
I'm using axios for HTTP requests in my react native app.
I'm implementing a live search component, and I want to cancel previous request so the final results don't get messed up. I'm implemented the canceltoken in my requests. This is my code so far (simplified):
const cancelToken = axios.CancelToken;
let source;
const liveSearch = async (searchQuery) => {
try {
if (source) {
source.cancel();
}
source = cancelToken.source();
const response = await axios({
method: 'get',
url: `http://x.ngrok.io/search/${searchQuery}`,
cancelToken: source.token
});
return response.data
} catch (err) {
if (axios.isCancel(err) {
console.log(`cancelled request: ${searchQuery}`);
}
}
};
As you can see, if first check if a source exists. If so, cancel it, and create a new source. Then I do the request with the cancelToken as an object property.
When I run my app and check the console output of my app, I see 'cancelled request' correctly. But, in ngrok, I still see the HTTP requests for the 'cancelled' requests. An example:
In console output app (searching for 'hello'):
- cancelled h
- cancelled he
- cancelled hel
- cancelled hell
In ngrok terminal window:
- GET /search/hello 304 Not Modified
- GET /search/hell 304 Not Modified
- GET /search/hel 304 Not Modified
- GET /search/he 304 Not Modified
- GET /search/h 304 Not Modified
Is there something wrong with my implementation of the axios canceltoken? Or is it 'normal' that ngrok logs all requests, even the cancelled ones?

Related

How do I check network response in playwright?

I want to test the network https status response with playwright.
test.only('Rights.2: Users without the required author role do not have access.', async ({page}) => {
await login(page, 'xxx', "password.xxx");
const search = await searchForProcess(page, `${process.process1.title}`);
await login(page, 'PortalUser');
const open = await openProcess(page, `${process.process1.title}`);
});
So I tried with this
expect(response.status()).toEqual(403);
But it won't work, because response is not defined. Thats curious, because Playwright does document the "response.status()" as a function.
Can somebody help?
You could try page.waitForResponse(). Official docs:
https://playwright.dev/docs/api/class-page#page-wait-for-response
Here is an example where we click a button and we want to monitor that certain API calls actually happen and that they have certain response statuses:
// Start waiting for all required API calls as we select company.
// We can accept only 200 but we could accept 403 like with /api/Environment/
await Promise.all([
page.waitForResponse(resp => resp.url().includes('/api/Environment/') && (resp.status() === 200 || resp.status() === 403)),
page.waitForResponse(resp => resp.url().includes('/api/Security/') && (resp.status() === 200)),
// We already started waiting before we perform the click that triggers the API calls. So now we just perform the click
page.locator('div[role="gridcell"]:has-text("text")').click()
]);
If you wish to validate other reponse data, see: https://playwright.dev/docs/api/class-response
If you want to monitor all network traffic, this official docs would be more suitable: https://playwright.dev/docs/network#network-events

HTTP request handler that sends an audio file from another URL as a response

I want to allow users request audio files. The files are hosted on a separate file server. I don't want users to get these files unless they've gone through my server first.
How do I make a function that basically acts as a middle man between the user and the file server. I currently have something like this:
async (req, res) => {
const mediaLink = `https://www.example.com/audio.mp3`;
const mediaResponse = await fetch(mediaLink, {
headers: {
Range: req.headers.range,
}
});
const blob = await mediaResponse.blob(); // I'm guessing here. Idk.
res.send(blob);
}
I tested this in an <audio> tag but the audio never loaded:
<audio controls src="http://localhost:5001/file-server-middleware" />
The correct way to handle such a request would be to pipe the response body back to the client making sure to copy across any relevant headers that may be in the response from the file server. Read up on the HTTP Functions documentation to see what use cases you should be looking out for (e.g. CORS).
async (req, res) => {
const mediaLink = `https://www.example.com/audio.mp3`;
// You may wish to pass through Cache-related headers, such as
// If-None-Match, If-Match, If-Modified-Since, If-Range, If-Unmodified-Since
const mediaResponse = await fetch(mediaLink, {
headers: {
Range: req.headers.range,
}
});
// note: this currently passes the body & status from the file server
// as-is, you may want to send your own body on failed status codes to
// hide the existence of the external server (i.e. custom 404 pages, no
// Nginx error pages, etc)
// mediaResponse.status may be:
// - 200 (sending full file)
// - 206 (sending portion of file)
// - 304 (not modified, if using cache headers)
// - 404 (file not found)
// - 412 (precondition failed, if using cache headers)
// - 416 (range not satisfiable)
// - 5xx (internal server errors from the file server)
res
.status(mediaResponse.status)
.set({
/* ... other headers (e.g. CORS, Cache-Control) ... */
'Content-Type': mediaResponse.headers.get('content-type'),
'Content-Length': mediaResponse.headers.get('content-length'),
'Content-Encoding': mediaResponse.headers.get('content-encoding'),
'Etag': mediaResponse.headers.get('Etag'), // for caching
'Last-Modified': mediaResponse.headers.get('last-modified') // for caching
});
mediaResponse.body.pipe(res);
}
You may also want to look into the various express-compatible proxy modules that can handle the bodies and headers for you. Note that some of these may not function properly if used in a Firebase Cloud Function as the request bodies are automatically consumed for you.

Why is XHR request pending forever on live server?

So i have a react app which if someone is logged in will check for it's account level and based on that will enable or disable features. It worked until it was all localhost, but now i have a server in the cloud and the request is pending forever. Other requests to the same endpoint works fine. I tried changing the address to localhost, but then it looks for the API server on my PC. It's strange because the same endpoint works with other requests. This single request also works on localhost but not if i use server's IP. Here's an image of the Network page of Chrome development tools: https://i.ibb.co/c2r8Js1/Screenshot-at-2019-12-27-15-11-41.png
getLoggedLevel = () => {
var URL = process.env.REACT_APP_API_URL;
var URL2 = 'http://localhost:8000/requests'
axios({
url: URL,
method: 'post',
data: {
message: 'getLoggedLevel',
username: JSON.parse(localStorage.getItem('loggedUser')).username
}
}).then(res => {
this.setState({loggedLevel: res.data.level})
})
}
Edit: I created a separate endpoint for that single request, and it's 404 however in firefox it's 200 for OPTIONS... Now i'm really confused :(

express cookie not set in response, not shown in next request

There are several moving parts, so it's difficult to know what to debug here.
I have a web application on one localhost port, and a simple helper on another localhost running an express NodeJS application with a couple of endpoints.
The basic issue I'm seeing is that my cookie session on the express application is empty for subsequent calls, and I don't even see it being sent back in the first response.
The setup
The client makes basic GET ajax calls (jQuery at the moment) to the express application.
I have set http allowance for session cookies:
app.use(cookieSession({
name: 'session',
keys: ['abcdefg'],
maxAge: 24 * 60 * 60 * 1000, // 24 hours,
secure: false
}))
I have set cross-origin requests on the express application:
app.use((req, res, next) => {
const corsWhitelist = [
'http://localhost:8000',
'http://localhost:8777'
];
if (corsWhitelist.indexOf(req.headers.origin) !== -1) {
res.header('Access-Control-Allow-Origin', req.headers.origin);
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
}
next();
});
And the requests are completed seemingly without issue, as the response bodies are what I expect.
The meat of the request handler is:
app.get('/initialize', (req, res) => {
console.log(req.session);
//if we have a session with verified status
if (req.session.hasOwnProperty("userId") && req.session.userId){
res.send({result: 'OK', message: 'good - 1'});
return;
}
const id = uuid.v4();
req.session.userId = id;
res.send({result: 'OK', message: 'good - 2'});
return;
});
I always always get the second response 'good - 2' from the ajax call. The log always shows the session as {}
It's probably worth noting that Chrome devtools shows "Provisional headers are shown" for the request headers, and set-cookie is not shown in the response headers. The AJAX is a simple GET to an endpoint with one parameter passed in.
Update
Just now occurred to me to try without using the AJAX call. Hitting the URL directly gets the cookie and keeps the session as expected. That will probably change the dynamic of the issue.
The fix was to use jsonp request/response to get cookies to pass around the ajax call. Nothing to do with express really.
https://samueleresca.net/2015/07/json-and-jsonp-requests-using-expressjs/

make a HTTP Request from React-Redux from localhost

I am new to React Redux, and All I already did:
1) activate my backend server (localhost:5000)
2) activate my front-end server using npm start (localhost:8080)
3) I tried to dispatch action by using
this.props.dispatch({type: ActionTypes.FILE_UPLOAD_REQUEST, email: this.state.email, file: this.state.policyFile});
4) Using atlas-saga, and call my service function associated with the dispatch :
let result = yield call(Atlas.uploadFile, action.email, action.file);
5) define the function as :
export const uploadFile = (email, file) => {
return fetch(`${BASE_URL}/v1/files/${email}/policies`, {
method: 'POST',
headers:{} ,
body: {'file': file}
})
.then(response => response.json())
}
After I try to run a function at my react( a function that calls the dispatch), it gives me errors that they cannot found the route. This is the error message from the console.
Fetch API cannot load https://api-staging.autoarmour.co/v1/files/fakeemail#gmail.com/policies. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access. The response had HTTP status code 500. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Yes, I did not create any reducer, just pure function that will upload a file. Thank you
I SOLVE IT, WOHOO!!!
The error message means that its not connected at the backend side at all. You need to make sure that it is connected. I solve it by connecting my redux to my react component. Thanks guys
Cheers!