I have a simple application (server side is Sinatra, client side is ReactJS).
The workflow is very basic: Sinatra handles get "/" request and sends an index.html to the client with static stylesheet and scripts.
Scripts are ReactJS app which consists of several components and a ReactRouter. Each React's component is a distinct "page" with its own route/path in terms of the ReactRouter.
For example:
"/" => "index.html" (real html page with renered components
inside),
"/form" => (ReactRouter points to component <Form/>, in fact render happens inside selector of "index.html"),
"/finish" => (ReactRouter points to component <Finish/>, in fact render happens inside selector of "index.html").
While I was implementing client side only, it worked pretty well. But now, when I am trying to use Sinatra for the server side stuff this is broken: when I want to go to the /form I am getting Sinatra's default 404 page ("Sinatra doesn’t know this ditty.").
I understand that Sinatra (or Rack) intercepts the request's path (/form of /finish) before the ReactRouter. But I cannot understand how to fix it (and why is it so, while router script is already on the client and should fire first).
Thanks for your help.
Use wildcard route to return index.html to all route.
Something like this:
get '/*' do
#return index.html
end
Related
I'm building a website where users can post ads : a VueJS app that requests routes on an Laravel API.
I have an AdController, with an Ad model, and my routing is done via stuff like :
Route::apiResource('ads', AdController::class)->only(['update', 'destroy']);
Route::apiResource('ads.photos', AdPhotoController::class)->only(['index']);
which generates routes like PUT "/ads/{ad}" or GET "/ads/{id}/photos"....
This works very well, and my VueJS app uses Ziggy to call the API by their route name
axios.get(route('ads.photos.index', id))
And... It still works flawlessly ! No problem at all, and I have a LOT of routes with a LOT of API calls.
Now my problem : we realised that URLs containing "ads" are blocked by adblockers. That completely shuts down all access to our website, and asking users to turn off the adblocker is NOT a solution.
I could change my routes to do something like
Route::apiResource('posts.photos', AdPhotoController::class)->only(['index']);
but I have a LOT of routes and I really don't want to rename everything, everywhere.
Is there an option to change apiResources generated URL, so 'ads.photos.index' would generate "/posts/{id}/photos" instead of "/ads/{id}/photos" ?
I have a Rails API backend and a ReactJS frontend. My backend sends custom emails that often have confirmation-like links (like email confirmation)
Should the confirmation links point to my backend directly, or should they rather load the frontend first and then make an API call to the backend?
The two alternatives I'm thinking of are:
1 - The email confirmation link hits directly
backend.example.com/email_confirmations/:confirmation_token, which then redirects to a specific success (error) page frontend.example.com/email_confirmation/success(/failure) on my frontend.
On the backend I would only need a Metal controller with minimum modules to perform redirection to the frontend app, the controller is always responding with redirects). If further actions need to be taken from the frontend, they'll hit a different API Endpoint
2 - The email confirmation links opens up my frontend at
frontend.example.com/email_confirmations/:confirmation_token that triggers an API request to backend.example.com/email_confirmations/:confirmation_token.
Then my (Json:api) backend makes a jsonapi-compliant response with a Rails APIController.
What are you doing in practice?
I decided to opt in for the first scenario but maybe systematically calling/loading the frontend first makes more sense?
How do you wire backend/frontend in those scenarios?
I have currently implemented a very simple (Metal) Controller that would just process the incoming parameters perform redirections only to the frontend. I was hoping to define "url helpers" that would point to my frontend like so:
namespace :email_redirection do
# Controller that gets hit by email confirmation links in scenario #1
resources :confirmations
end
namespace :frontend do
frontend_root = Rails.configuration.frontend_host_with_http_and_port
scope frontend_root do
# Generation of URL Helpers for the frontend app
resources :confirmations, only: [] do
get 'successful'
get 'unsuccessful'
end
end
end
And my confirmation controller would be like
class EmailRedirection::ConfirmationsController
def index
svc = MyConfirmationService.new(token: params[:confirmation_token])
if svc.confirm
redirect_to(
frontend_successful_confirmation_url,
email: svc.confirmable.email
)
else
redirect_to(frontend_unsuccessful_confirmation_url)
end
end
end
I'm getting several error and I believe maybe the url helpers are not useable with different host/port... (or I have to pass them explicitely to each call)
How can I handle that ? And if 1. is a good choice, what would be the redirection codes you'd send on success/failure (since they can only be 3xx) ?
Both solutions involve quite some wiring between the backend/frontend and I'm not sure how to best wire things up.
Note : my models use devise but because devise isn't so great with APIs/etc. I'm using my own ConfirmationService that also handles some side-effects. I don't consider Devise to be relevant here
Creating a rails route to an external URL
What is the correct way to route your request through Sinatra so that it serves up the file with no processing? I'm looking for the most common way people do this in the Sinatra framework? I normally place all of my static content in a "content" path.
examples:
/content/css
/content/img
/content/js
How can I use a wildcard to serve up everything under content?
I was surprised there were no real examples of this here:
http://sinatra-book.gittr.com/
Sinatra and Rails use the path public for static content - e.g., ./public/javascripts/. All files in these paths would then be served by the web server (e.g. Thin, Passenger), but without the need for /public in the URL (e.g. the file at #{my_app_root}/public/javascripts/application.js would be available via the Web at the URL http://#{my_domain}/javascripts/application.js).
get '/notes/images/:file' do
send_file('/root/dev/notes/images/'+params[:file], :disposition => 'inline')
end
A django web app needs to make ajax calls to an external url. In development I serve directly from django so I have a cross domain problem. What is the django way to write a proxy for the ajax call?
Here's a dead simple proxy implementation for Django.
from django.http import HttpResponse
import mimetypes
import urllib2
def proxy_to(request, path, target_url):
url = '%s%s' % (target_url, path)
if request.META.has_key('QUERY_STRING'):
url += '?' + request.META['QUERY_STRING']
try:
proxied_request = urllib2.urlopen(url)
status_code = proxied_request.code
mimetype = proxied_request.headers.typeheader or mimetypes.guess_type(url)
content = proxied_request.read()
except urllib2.HTTPError as e:
return HttpResponse(e.msg, status=e.code, mimetype='text/plain')
else:
return HttpResponse(content, status=status_code, mimetype=mimetype)
This proxies requests from PROXY_PATH+path to TARGET_URL+path.
The proxy is enabled and configured by adding a URL pattern like this to urls.py:
url(r'^PROXY_PATH/(?P<path>.*)$', proxy_to, {'target_url': 'TARGET_URL'}),
For example:
url(r'^images/(?P<path>.*)$', proxy_to, {'target_url': 'http://imageserver.com/'}),
will make a request to http://localhost:8000/images/logo.png fetch and return the file at http://imageserver.com/logo.png.
Query strings are forwarded, while HTTP headers such as cookies and POST data are not (it's quite easy to add that if you need it).
Note: This is mainly intended for development use. The proper way to handle proxying in production is with the HTTP server (e.g. Apache or Nginx).
I ran across this question while trying to answer it myself, and found this Django app:
http://httpproxy.yvandermeer.net/
...which is a little heavyweight for what I needed (recording and playback, requires a syncdb to add in model stuff). But you can see the code it uses in its generic proxying view, which is based on httplib2:
http://bitbucket.org/yvandermeer/django-http-proxy/src/1776d5732113/httpproxy/views.py
Am I right that you are asking about how to write view in Django that could accept incoming AJAX request, issue request to the remote server and then return received response to browser?
If so, then it's not really Django-specific question - remote calls could be done with Python's urllib2 or httplib, and then you just have to put:
return HttpResponse(received_response)
-- in your Django proxy-view. I assume no reponse processing here, because if it's just a proxy for AJAX call then JavaScript expects unprocessed data.
I am developing a http module that hooks into the FormsAuthentication Module through the Authenticate event.
While debugging i noticed that the module (and all other modules registered) gets hit every single time the client requests a resource (also when it requests images, stylesheets, javascript files (etc.)).
This happens both when running on a IIS 7 server in integrated pipeline mode, and debugging through the webdev server (in non- integrated pipeline mode)
As i am developing a website with a lot images which usually wont be cached by the client browser it will hit the modules a lot of unnessecary times.
I am using MVC and its routing mechanishm (System.Web.Routing.UrlRoutingModule).
When creating a new website the runAllManagedModulesForAllRequests attribute for the IIS 7 (system.webServer) section is per default set to true in the web.config, which as the name indicates make it call all modules for every single request.
If i set the runAllManagedModulesForAllRequests attribute to false, no modules will get called.
It seems that the reason for this is because of the routing module or mvc (dont know excactly why), which causes that the asp.net (aspx) handler never gets called and therefore the events and the modules never gets called (one time only like supposed).
I tested this by trying to call "mydomain.com/Default.aspx" instead of just "mydomain.com/" and correctly it calls the modules only once like it is supposed.
How do i fix this so it only calls the modules once when the page is requested and not also when all other resources are requested ?
Is there some way i can register that all requests should fire the asp.net (aspx) handler, except requests for specific filetype extensions ?
Of course that wont fix the problem if i choose to go with urls like /content/images/myimage123 for the images (without the extension). But i cant think of any other way to fix it.
Is there a better way to solve this problem ?
I have tried to set up an ignoreRoute like this routes.IgnoreRoute("content/{*pathInfo}"); where the content folder contains all the images, javascripts and stylesheets in seperat subfolders, but it doesnt seem to change anything.
I can see there a many different possibilites when setting up a handler but I cant seem to figure out how it should be possible to setup one that will make it possible to use the routing module and have urls like /blog/post123 and not call the modules when requesting images, javascripts and stylesheets (etc.).
Hope anyone out there can help me ?
Martin
The problem seems to be the routing module.
The solution is to move images, css, js to a subdomain, or you can probably register which filetypes/extensions the routing module should ignore.
The following code is what I use in every MVC Application in order to avoid the overhead caused by the routing system on serving static files, javascript, css, etc:
public static void RegisterRoutes(RouteCollection routes)
{
routes.RouteExistingFiles = false;
routes.LowercaseUrls = true;
routes.AppendTrailingSlash = true;
routes.IgnoreRoute("Content/{*pathInfo}");
routes.IgnoreRoute("Scripts/{*pathInfo}");
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("{*favicon}", new { favicon = #"(.*/)?favicon.ico(/.*)?" });
/* ... */
}