Identify Origin/Source of FetchEvent Request - service-worker

Is there any way for a ServiceWorker to identify the source or origin of a no-cors/opaque FetchEvent.Request? Or can we explicitly pass identifying information/data from the HTML to the ServiceWorker that could be used to identify origins of FetchEvents?. I hacked together a solution using query string parameters, but I'm looking for something more native or elegant than this:
HTML
<img id="img1" src="image.jpg?imgId=img1" />
<img id="img2" src="image.jpg?imgId=img2" />
Service Worker
self.addEventListener('fetch', event => {
const url = new URL(event.request.url);
if(url.pathname.endsWith('/image.jpg')) {
// get Element ID that initated the FetchEvent
const imgId = url.searchParams.get('imgId');
// Notify document that the fetch started
clients.get(event.clientId)
.then(client => client.postMessage({imgId}));
}
})

First off, from the point of view of the service worker's fetch handler, the fact that the request has a mode of 'no-cors' shouldn't change anything. Opaque responses are a thing in order to prevent information leakage from third-party servers, but when you're talking about a request that originated from your own page being intercepted by your own service worker, there isn't the same concern about information leakage.
So, in general, the question is whether there's a way to get the browser to add in extra identifying information to the requests it implicitly creates for any subresource referenced in your DOM. Taking a look at the fields exposed in the Request object, there really isn't anything other than url that you have control over and could potentially set to something useful for identifying your outgoing requests. (You won't be able to control the headers for the implicitly created requests used for subresources referenced in your DOM.)
If you wanted to prevent the "noise" of using parameters to add in the identifying information to the url, you should be able to get away with using hash fragments, like
<img id="img1" src="image.jpg#img1">
<img id="img2" src="image.jpg#img2">
The service worker specification states that the hash fragment should be included in the request.url that's passed in to your fetch handler, so you can read it from there, but it won't actually be sent to the remote server.
(One of the things that you can get is the destination of a Request object, if you wanted to distinguish between requests which will be used for images, fonts, scripts, etc. But that won't allow you to identify which specific <img> was responsible for a given image request.)

Related

JMeter: How can I capture the variable value which is dynamic in url?

We have a URL https://www.mylink.com/est?myId=4d22b9d0-4ff2-46c3-9343-945304dfea93
The above request also contains post data:
myId=4d22b9d0-4ff2-46c3-9343-945304dfea93
How can I parameterize this as the url and post data both contain same value but its dynamic. Also, how may I store it in a variable to use it somewhere else as well?
In order to be able to use it in URL and request body you need to extract it somewhere somehow, this dynamic ID is probably associated with this or that user account so my expectation is that after logging in you should see this ID somewhere in the response.
The process is known as correlation and there is a plenty of information over the web about handling dynamic requests in JMeter. There are also solutions which provide semi or fully automated correlation of the dynamic parameters like Correlations Recorder Plugin for JMeter or JMeter Proxy Recorder
If you just need to generate an unique GUID-like structure - you can do it using __UUID() function

How to handle URLs that aren't controlled by a service worker

My strategy for service worker is if the url matches some particular format then only service worker should intercept it ,otherwise browser should handle it as it does normally ,
for all cases i am using evt.respondWith(), to intercept it and serve a custom response , but what should i do if the url does not match any of the format
I have couple of option and all of them works , but i am not sure which one is logically correct
1)do nothing , means i am having if conditions for checking each of the defined format inside the fetch method but if they do not match i do nothing , i dont have any "else" condition.In this case browser is fetching the page normally , but i am not sure if it is correct , what is actually happening , is cookies getting passed ?
2)inside the else method i have fetch(event.request, { credentials: 'include' });
this also works , i am not sure if i need to include the credential clause here , as per my understanding not service worker but browser is handling the request here , so it will automatically include the cookies . Please correct me if i am wrong here .
3)event.respondWith(fetch(event.request, { credentials: 'include' }));
This also works, i think since i am using event.respondWith, here i need to include the credential explicitly(again i am not sure).But my doubt is do i need to use event.respondWith here. What i know about event.respondWithis that, we use this only if we want to serve a custom response for a fetch event .As we want these requests to be handled as it is , do we need to use event.respondWith here ?
All of my confusions are coming from my lack of knowledge about event.respondWith(), could somebody please explain , exactly when should i use
it ?
event.respondWith allows you to respond to a network request with a response that you create (either by using fetch, or the Cache API, or even created manually with the Response constructor).
If you don't call it in the fetch event handler, the browser will handle the request.
If you call it with fetch(event.request), it's basically the same as letting the browser handle it (because fetch is going to perform exactly the same request the browser would have performed if you hadn't called event.respondWith).
Note that event.respondWith will respond with the value you pass to it or with the value that the promise you pass to it is resolved to.
event.respondWith(new Response('Some body.'));
event.respondWith(new Promise(function(resolve, reject) {
setTimeout(function() {
resolve(new Response('Some body.'));
}, 1000);
}));

MVC URL: show 1 parameter & hide second

Suppose I have URL as
http://someurl.com/Search?q=a&page=8
(Above mentioned URL is getting called throug AJAX, in MVC4.paging)
What I want is to show only upto http://someurl.com/Search?q=a
I want to hide my second parameter which is page=8
Is this possible?
EDIT: More confusion to add.
<a data-ajax="true" data-ajax-loading="#divLoading" data-ajax-method="POST" data-ajax-mode="replace" data-ajax-success="successPaging" data-ajax-update="#searchresults" href="/Search?q=a&page=1" title="Go to first page"><<</a>
Is button of Next in my Paging, it is making an AJAX request, So I don't know how to change GET to POST for this.
The URL isn't there just for looks; it's telling the server what resource is being requested, and in the case of a query string, that's information the server needs to return a response. http://someurl.com/Search?q=a is a completely different resource than http://someurl.com/Search?q=a&page=8. With a GET request, all you have is the URL, so all the information the server needs must be in the URL. What others in the comments are telling you to do is use a POST request, which among other things includes a post body. In other words, you can pass information to the server both in the URL and in the post body. That allows you to remove the page parameter from the URL and include it in the post body instead. That's the only way you can achieve what you want.
That said, strictly speaking, a POST is inappropriate for fetching a resource like this. POST should be used to update or modify a resource or to call some atomic method in an API scenario. It can also be used for the creation of resources, although PUT is more appropriate there. GET is supposed to be used to return a resource which is not variable. For example, any request to http://someurl.com/Search?q=a&page=8 should always return the same response no matter what client requests it. And, it's even less important what URL is actually being used because the user does not see it at all, since you're requesting it via AJAX (it won't show in the navigation bar). Just keep it as a GET request and leave the parameters as they are.

Get current fragment in Route, ASP.net MVC

Is there away to get the current fragment from a route that was issued via action link. This is how I am getting the action from the route.
string currentAction = requestContext.RouteData.Values["action"] as string ?? "index";
Can I do something similar to this?
string currentFragment = requestContext.RouteData.Values["Fragment"] as string ?? "";
No, you can't do anything like this. The fragment (everything that follows the # sign in an url) is never sent to the server by the browser, so the sole fact of talking about getting the url fragment server side simply doesn't make sense.
So if you have the following url: http://example.com/foo/bar?key1=value1#abc the server will never be able to fetch abc simply because the client will never send it.
As it has already been pointed out that is not possible. Document fragments (the string after the hash as you call it) are intended for the browsers only to correctly position the viewport. They have no meaning for the server and therefore are not transmitted there.
There is however a workaround you can use. Repeat the fragment as part of your url to make it accessible for the server.
Look at the permalink to the answers in this question. For instance, the link to my answer looks like this:
http://stackoverflow.com/questions
/6285833/get-current-fragment-in-route-asp-net-mvc/6286097#6286097
See how the value 6286097 is duplicated as the last route parameter. It's intentional. You can use this technique as well.
P.S. The fragment must point to an identifier in the document (id of some HTML element). At least in XHTML only identifiers work as fragments. Valid ids may not begin with a digit therefore instead of #6286097 use something like #answer-6286097.
P.S.#2. Do not use any JavaScript trickery to get around this limitation. Basic site functionality and design must work without JavaScript - don't listen to anyone who tells you otherwise. Fragments obviously belong to the basic tool box. Use JavaScript only for advanced interactivity.
I have a workaround for you, but first of all lets get more into the problem.
The strings after the hash symbol which are called Fragment values are not query parameters but they are strings to be read by the client-side (living in the browser) and the server cannot read them because they are not sent to the server by the browser.
Some authentication providers like Google and Azure send the access token as Fragment value for security reasons so that they are not transferred over the internet after they get sent as direct response from the authentication provider.
The only way you can come around that is to use javascript to convert the fragment values to query parameters by replacing the '#' with '?' and redirecting to the endpoint in your server controller.
I suppose the easiest way is to handle all that from server, meaning you get get the request in server, send a javascript code to the browser on the fly, that replaces the '#' into '?' and redirects to your second endpoint which reads the token as strong parameter.
Here how you can do it in ASP.NET Core 3.1:
[AllowAnonymous]
[HttpGet("authredirect")]
[Produces("text/html")]
public virtual ContentResult ConvertUrlFragmentToQueryParamThenRedirect()
{
return Content("<html><script>window.location.href=window.location.href.replace('#', '?').replace('authredirect', 'authparams')</script></html>", "text/html");
}
[AllowAnonymous]
[HttpGet("authparams")]
public virtual void GetAccessToken([FromQuery] string access_token)
{
// now you have your access token server side here
}
Please remember to set your redirectUrl to the correct one, in this case 'YOUR REDIRECT URL/authredirect'.

GET vs. POST (form processing)

I completely understand the differences between the two in terms of form handling, user discretion and privacy of data, but in what situation would anyone rather use GET over POST when sending form results?
Thanks
W3C HTML 4.01 Recommendation on the appropriate usage of GET and POST:
The "get" method should be used when the form is idempotent (i.e., causes no side-effects). Many database searches have no visible side-effects and make ideal applications for the "get" method.
If the service associated with the processing of a form causes side effects (for example, if the form modifies a database or subscription to a service), the "post" method should be used.
Note: The "get" method restricts form data set values to ASCII characters. Only the "post" method (with enctype="multipart/form-data") is specified to cover the entire [ISO10646] character set.
GET places parameters in the URL itself, allowing everyone to see. While POST would be ideal for logins and security-sensitive data, GET is ideal when you want a dynamic page to be bookmarked.
Take a forum for example. The thread which shows all posts within it is loaded dynamically. There doesn't exist a page for every thread available, meaning parameters must be provided which indicate which thread to load. These parameters are passed using GET so that you can bookmark the page and that exact URL with the parameters provided will be used again to load the page.
For instance, to make form data visible in logs.
If i need that user can save a bookmark of next step/page (for whatever reason) i would use GET other than that probably POST.
Both are unsafe and you must escape both.

Resources