I have a simple Sinatra proxy, which when an endpoint is called, will redirect to another endpoint on the same Sinatra proxy.
When I make a request with a header, the proxy doesn't seem to pass this header through to the second endpoint when the request redirects in the first. This is my code:
get '/first' do
# get the header from the request
username = env['HTTP_USERNAME']
# set the header for the response
response['username'] = username
redirect '/second'
end
get '/second' do
# This doesn't exist when redirected from /first
puts env['HTTP_USERNAME']
# Here is a list of all headers
env.each_key do |key|
puts "KEY: #{key} VALUE: #{env[key]}" unless key.nil?
end
"DONE"
end
Any tips would be greatly appreciated.
Thanks
That is intentionally. redirect triggers an HTTP redirect, a new request will be fired. Also, passing on env values is done via modifying env, not response.
The main question is, what do you mean by header? Request header or response header? From your example I figure you mean request header, therefore response['username'] = username should be request.env['username'] = username. You could then replace redirect '/second' with request.path_info = '/second'; pass to do some sort of internal redirect. If you don't pass the value on to another Rack middleware/endpoint, you could also store the user name in an instance variable.
get '/first' do
request.path_info = '/second'
pass
end
get '/second' do
puts request.env['HTTP_USERNAME']
"DONE"
end
Related
I am trying to make a call to an authorization endpoint using OAuth2 with grant type Client Credentials - my call is successful - that is not an issue. However, I, now, want to take the access token that is returned and put it in a variable so I may use it in subsequent calls without having to manually cut-and-paste to my other calls.
When the call returns I see the token I desire to copy in the Access Token field at the bottom of the OAuth2 window (the one shown below that says expires in 42 minutes) AND I see it in the Authorization field on the Timeline tab of the results. I just can't figure out how to get access to it so I may dump it into variable.
The gif on the FAQ goes really fast, and does not provide step by step. Also, I didnt find any answer on YouTube or other websites, so I thought to share step by step for chaining requests on Insomnia.
Create a POST query to obtain your access token. Notice that my access token is returned in the field called "access_token", we will use this in step 3. Your return field may be different.
Create a second GET request for the API that would return the data for you. In my case, I wanted to get all users from a SCIM interface. In the Bearer tab, type in Response => Body Attribute (Insomnia will autofill).
Mouse click on the Request => Body Attribute (the one you just typed in), and select the authentication post in the dropdown "Request" (this is the one you created in step 1), and in the "Filter (JSONPath)" field, type in the $.[attribute name] - where attribute name is the response that returns from authentication call. In my case, it was access_token, see step 1 for yours.
Enjoy!!
Click No Environment > Manage Environments and you will see a base environment in JSON.
Since this is in JSON, create a { "jwt_token": "Response => Body Attribute" }" pair for your token variable. Please note that "Response => Body Attribute" needs to be configured. When you type response, hit space and this option should be available.
Once done choosing "Response => Body Attribute", it will show with some gibberish content and with red background, no worries... just click it to configure. Make sure you have the same setup.
However... you need to change your request to the route where you get the token from the server and another thing is the Filter (JSONPath or XPath) change it depending on your setup.
You should have the token, stored in jwt_token variable and can use the variable on a route that you like.
Example:
If you want to save a token that is returned in a response into an environment variable, you can use request chaining in your environment variable. Take a look at this url for more details on that https://support.insomnia.rest/article/43-chaining-requests...
Here is what you could do (what I did)
Create an environment variable
For the value of the variable, use the Response => Body Attribute and under Filter (JSONPath or XPath), choose the attribute of the token in your response body (if it is "token" then put $.token).
After that just put the token environment variable wherever you need it in the following requests.
I was not able to resolve this question but was able to get around it by defining the fields in the body of the request and bypassing the OAuth2 tab completely.
You can add it as a header, by referencing the outputs of the OAuth2 request:
My team has just started creating RESTful services for data that has previously been handled by a large monolithic legacy application. We want to document the api with Swagger UI and I have set up with one problem.
I need to pass a SAML token as a header parameter, otherwise when we try to click on the "Try it out!" button I get a 401 Authentication error. How do I add a field to the Swagger UI so that someone can put a String for a SAML token to be sent in the request?
This is actually really easy. I saw references to the answer in the documentation but I didn't really understand what it was saying. There is a field at the top next to where your service URL goes and you can use that field to input a string to pass as a header value. That input field has an id of #input_apiKey.
Then in the index.html file you just add a line to the addApiKeyAuthorization() javascript function telling it to take the value of that field and pass it as whatever value you need.
Example:
function addApiKeyAuthorization(){
var key = $('#input_apiKey')[0].value;
if(key && key.trim() != "") {
swaggerUi.api.clientAuthorizations.add("samlToken", new SwaggerClient.ApiKeyAuthorization("samlToken", key, "header"));
swaggerUi.api.clientAuthorizations.add("Content-Type", new SwaggerClient.ApiKeyAuthorization("Content-Type", "application/json", "header"));
swaggerUi.api.clientAuthorizations.add("Accept", new SwaggerClient.ApiKeyAuthorization("Accept", "application/json", "header"));
}
}
$('#input_apiKey').change(addApiKeyAuthorization);
This sets the Content-Type and Accept headers to the same values for every request, and takes the value in that input field at the top of the page in the green header and sets it as my SAML token. So now if I paste in a valid SAML string my request works and I get data back!
I was experimenting with building a Google Spreadsheet where:
Column A is a list of URLs that should be 301 redirected
Column B was our intended URL to be redirect to
Column C is the server response code when hitting Column A
Column D is the URL that was ultimately served up when hitting Column A
Column E is a Boolean for B and D matching
I'm having problems with populating column D. Here is what I tried:
function getHeaders(tURL) {
var response = UrlFetchApp.fetch(tURL);
var tHeaders = response.getAllHeaders();
}
I was expecting that "location" would be in the response header. But it seems this method only returns a handful of server response headers. I get: X-Frame-Options, Date, P3P, Content-Length, Expires, X-XSS-Protection, Content-Encoding, Alternate-Protocol, Set-Cookie (array), Content-Type, Server, Cache-Control.
Question
Any suggestions on another way to get to location? Or an alternate idea on how to determine where the url was redirected to?
You need to use fetch(url, params) method of UrlFetchApp class and supply followRedirects parameter set to false:
var response = UrlFetchApp.fetch(tURL, {'followRedirects':false});
followRedirects defaults to true, and thus your request returns the headers and content of the page it was redirected to, not the requested page. That is why you do not see the Location header there.
Is there a way to handle a GET request on Sinatra and make a PATCH request with a different body on the same server? User makes a request GET /clean_beautiful_api and server redirects it to PATCH /dirty/clogged_api_url_1?crap=2 "{request_body: 1}"?
I want to clean up legacy API without interfering with the functionality.
If I've understood correctly, the easiest way is to extract the block used for the patch into a helper:
patch "/dirty/clogged_api_url_1"
crap= params[:crap]
end
to:
helpers do
def patch_instead( params={} )
# whatever you want to do in here
crap= params[:crap]
end
end
get "/clean_beautiful_api" do
patch_instead( params.merge(request_body: 1) )
end
patch "/dirty/clogged_api_url_1"
patch_instead( params )
end
Or you could use a lambda…
Patch_instead = ->( params={} ) {
# whatever you want to do in here
crap= params[:crap]
}
get "/clean_beautiful_api" do
Patch_instead.call( params.merge(request_body: 1) )
end
# you get the picture
the main thing is to extract the method to somewhere else and then call it.
Edit: You can also trigger another route internally using the Rack interface via call.
I want to redirect the user back to the path from which he started the request.
Example:
/profile
/profile/edit
/profile
OR:
/products
/profile/edit
/products
What do I have to set for this redirection mode?
Inside your controller for /profile/edit you can capture the page they came from with $request->headers->get('referer').
If /profile/edit is a page with a single form, I'd probably just add a hidden field that says where the redirect should go.
public function editAction(Request $request)
{
// If you have a POST value coming from the user, it will be used, otherwise
// assume this is the first time they landed on the page and grab the current
// referer. With this method it doesn't matter how many times they submit the form
// you won't accidentally overwrite the referer URL with /profile/edit. That could
// lead to a confusing loop.
$referer = $request->request->get('referer', $request->headers->get('referer'));
if ($formIsSaved)
{
return new RedirectResponse($referer)
}
return array(
// Your template should include a hidden field in the form that returns this.
'referer' => $referer,
);
}
You could pass a redirect path as a GET parameter — say, redirectTo — to the edit page and after the edit process is complete, redirect to that path.
return new RedirectResponse($request->query->get('redirectTo');
You could make it more robust by checking whether or not that parameter is provided, and if it isn't, redirect to some sort of a default path.