Capybara 'visit' is not considering '#' character in URL? - ruby

Im running into a strange issue, I have my app host set to a remote site like so:
Capybara.configure do |config|
config.default_max_wait_time = 10 # seconds
config.default_driver = :selenium_chrome
config.app_host = 'https://dev.stagingsite.com/widget-web/#/'
end
All relative paths come after the /#/, so in my visit methods (such as session.visit('login') will take me to the URL:
https://dev.stagingsite.com/widget-web/login#/
I've tried adding '/' in various places, escaping the # but it seems to not be able to put relative url's after the # and instead always tries to put it after the widget-web/
Any ideas what is going on here?

From MDN's URL documentation:
It is worth noting that the part after the #, also known as the fragment identifier, is never sent to the server with the request.
Check your server logs; you'll see that any request to /widget-web/#/ is sent as a request to /widget-web/. The # prevents anything after it from being sent to the server.
What is a URL? docs

UPDATE Actually after thinking about this a while it would probably do what you want if you did visit '#login' since the fragment passed in visit would get merged over the app_host fragment
Capybara visit doesn't just append to app_host - it parses app_host and what's passed to visit and merges them. visit accepts either a full url or a relative path, what you're trying to set is the URL fragment - which visit has no way of identifying as what you want to do - https://en.wikipedia.org/wiki/Fragment_identifier. If you want to be setting the fragment in browser you're going to need to pass a full URL to visit (possibly by using your own helper function to build the URL you want)

Related

How can I get URL information following "#" in Koa

I have a URL that in the browser shows like this https://localhost:3000/location#valueIwant=1234.
I am trying to get access to the valueIwant value but all of the items I try ctx.request.path, ctx.request.href, etc but all seem to not have the values after #. How do I parse this part of the url.
Also this is coming from a redirect.
Everything after the # is not sent to the server. The purpose of the fragment is to create a link to a specific subsection of a page.
If you want to send specific parameters to the server, the right way to do it is to use the query part (everything after ?), not the fragment part. This is by design.

How to tell Faraday to preserve hashbang in site URL?

I'm working on a fork of a library that implements Faraday to build URLs.
site = "https://example.io/#/"
path = "oauth/authorize"
connection = Faraday.new(site)
resource = Faraday::Utils.URI(path)
URL = connection.build_url(resource)
Notice that my site URL ends with a hashbang. But when the above code is executed, Faraday strips out the hashbang entirely:
https://example.io/oauth/authorize
But my application requires it to build this URL (with the hashbang):
https://example.io/#/oauth/authorize
Now before I go ripping out Faraday and monkey-patching something terrible.. can I do this by setting an option on Faraday?
I think the answer here would be to quit trying to preserve the hash portion of the URL in Faraday since that portion is ignored for HTTP requests.
The hash part of the URL (also known as URI "fragment identifier") is never sent to the server. It can only have a meaning in the client. Typically, when the HTTP client is a web browser, the fragment identifier holds the name of the element to scroll to. Or, hashbang tricks can be employed with some JavaScript interaction.
But to use such URLs in Faraday doesn't make sense because the hash portion will never get sent to the server anyway.
Having '#' in path variable instead of site variable i am getting the output as you require.
site = "https://example.io/"
path = "#/oauth/authorize"
connection = Faraday.new(site)
resource = Faraday::Utils.URI(path)
URL = connection.build_url(resource)
Please try the above code and let me know the result.

AJAX search - parsing and reading the URL parameters with hash tags

we've implemented a new AJAX based search on our website. We're adding the parameters and their values with # tag at the end of the main URL, when user makes further refine by applying additional filters.
This was done to enable our users to share the URL of what they were viewing. It's actually now achieved in a way that the page gets redirected and the content is generated first for the base URL. Using a Javascript function which executes onload looks at the parameters in the # tags and makes another AJAX hit.
Questions:
Why browsers are not sending the # thing to the server. i.e.; # part is not even received by the HTTP Server. It's interesting actually, browsers are not sending them at all
What is best way to get the # values? I'm looking at more of to avoid the double hit that we've implemented right now. i.e.; content is loaded already and then making another AJAX call to apply the refines.
The # value is an instruction to the browser to look for a named anchor in the document it is to load from the server. It is interpreted and actioned by the browser. The server can do nothing with it, so there's no point in sending it. If you're trying to use this for some other purpose then you'll run into difficulties - as you have found.
There is a mechanism for sending data to the server: the querystring. Append your parameters to the URL prefixed by a ?, in the form variablename=data, with successive variables separated by a &.

Grab Facebook signed_request with Sinatra

I'm trying to figure out whether or not a user likes our brand page. Based off of that, we want to show either a like button or some 'thank you' text.
I'm working with a sinatra application hosted on heroku.
I tried the code from this thread: Decoding Facebook's signed request in Ruby/Sinatra
However, it doesn't seem to grab the signed_request and I can't figure out why.
I have the following methods:
get "/tab" do
#encoded_request = params[:signed_request]
#json_request = decode_data(#encoded_request)
#signed_request = Crack::JSON.parse(#json_request)
erb :index
end
# used by Canvas apps - redirect the POST to be a regular GET
post "/tab" do
#encoded_request = params[:signed_request]
#json_request = decode_data(#encoded_request)
#signed_request = Crack::JSON.parse(#json_request)
redirect '/tab'
end
I also have the helper messages from that thread, as they seem to make sense to me:
helpers do
def base64_url_decode(payload)
encoded_str = payload.gsub('-','+').gsub('_','/')
encoded_str += '=' while !(encoded_str.size % 4).zero?
Base64.decode64(encoded_str)
end
def decode_data(signed_request)
payload = signed_request.split('.')
data = base64_url_decode(payload)
end
end
However, when I just do
#encoded_request = params[:signed_request]
and read that out in my view with:
<%= #encoded_request %>
I get nothing at all.
Shouldn't this return at least something? My app seems to be crashing because well, there's nothing to be decoded.
I can't seem to find a lot of information about this around the internet so I'd be glad if someone could help me out.
Are there better ways to know whether or not a user likes our page? Or, is this the way to go and am I just overlooking something obvious?
Thanks!
The hint should be in your app crashing because there's nothing to decode.
I suspect the parameters get lost when redirecting. Think about it at the HTTP level:
The client posts to /tab with the signed_request in the params.
The app parses the signed_request and stores the result in instance variables.
The app redirects to /tab, i.e. sends a response with code 302 (or similar) and a Location header pointing to /tab. This completes the request/response cycle and the instance variables get discarded.
The client makes a new request: a GET to /tab. Because of the way redirects work, this will no longer have the params that were sent with the original POST.
The app tries to parse the signed_request param but crashes because no such param was sent.
The simplest solution would be to just render the template in response to the POST instead of redirecting.
If you really need to redirect, you need to carefully pass along the signed_request as query parameters in the redirect path. At least that's a solution I've used in the past. There may be simpler ways to solve this, or libraries that handle some of this for you.

Sinatra Url '/' interpretations

I am a ruby newbie and have been trying Sinatra for quite some time now, one thing that Iam not able to figure out is why does a '/' in the url make such a big difference.
I mean isnt:
get 'some_url' do
end
and
get 'some_url/' do
end
Supposed to point to the same route? why is that Sinatra considers it as different routes? I spent a good one hour trying to figure that out.
According to RFC 2616 and RFC 2396 (RFCs defining resource identity) those URLs do not define the same resource. Therefore Sinatra treats them differently. This is esp. important if you imagine the route returning a page with relative links. This link
click me
Would point to /bar if you're coming from /foo, to /foo/bar if you're coming from /foo/.
You can use the following syntax to define a route matching both:
get '/foo/?' do
# ...
end
Or the Regexp version mentioned in the comments above.
They are different routes. The second is a URL with a directory extension ('/'); the first is a URL with no extension. A lot of frameworks (like Rails) will interpret both as the same route, or append the `/' (e.g., Django, and Apache can be configured to do that as well), but technically they are different URLs.

Resources