Multiple domains on single Nuxt app deplyed on Vercel - url

I've an Nuxt app, deployed on Vercel, xpto.vercel.app with specific client routes:
xpto.vercel.app/client-a
xpto.vercel.app/client-b
xpto.vercel.app/admin
I have 3 domains, I don't know if this is possible, but there is any way to point each domain to that client specific route? (with only one project on vercel)
www.client-a.com => xpto.vercel.app/client-a
www.client-b.com => xpto.vercel.app/client-b
www.app-admin.com => xpto.vercel.app/admin
This is my current solution, but it's far from ideal, and requires FTP.
.htaccess
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)$ index.php [QSA,L]
</IfModule>
index.php
<?php
$project = "client-a";
$url = "https://xpto.vercel.app/" . $project . $_SERVER['REQUEST_URI'];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$data = curl_exec($ch);
curl_close($ch);
echo $data;
?>

From Vercel Support:
Thank you for reaching out to Vercel Support.
Unfortunately, this is not possible in a single Vercel project.
Let us know if you have any further questions or concerns.

Related

Curl post returning bad request in HaProxy http-request redirect configuration

Here im trying to rewrite the URL in HaProxy, the get method is working as expected but I'm facing issue with the POST method; Elaborating the issue below
What im trying to do:
Whenever someone request for http://preprod.mydomain.com/app_a/* it should go to >> http://preprod.mydomain.com/something/app_a/*(It's Working as expected with GET method)
My HaProxy configuration:
acl mydomain_domain hdr(host) -i preprod.mydomain.com
acl app_a_redirection path_beg -i /app_a
http-request set-header X-Location-Path %[capture.req.uri] if app_a_redirection mydomain_domain
http-request replace-header X-Location-Path [^/]+/(.*) \1 if app_a_redirection mydomain_domain
http-request redirect location http://preprod.mydomain.com/something/app_a/%[hdr(X-Location-Path)] code 307 if app_a_redirection mydomain_domain
Adding Error details while POST:
Request URL:
curl --location --request POST 'https://preprod.mydomain.com/app_a/something-1/something-2' \
--header 'Content-Type: application/json' \
--data-raw '{
"user_id": "xxxxxxxxxxxx",
"app_id": "xxxxxxxxxxxx",
"app_version": "1.0.0",
"client_session_id": "xxxxxxxxxxxx",
"xpath": "xxxxxxxxxxxx",
"device_id": "xxxxxxxxxxxx",
"events": "xxxxxxxxxxxx"
}'
Error: {"timestamp":"2020-08-18T06:57:16.037+0000","status":400,"error":"Bad Request","message":"Required request body is missing: public com.mydomain.something.response.UploadedEventResponse com.mydomain.something.controllers.MobileAppController.postAppEvents(com.mydomain.something.core.models.request.EventsDTO) throws java.lang.Exception","path":"/something/app_a/something-1/something-2"}
POST and redirect does not work as you expect. See Post/Redirect/Get for the flow.
Looks like you want to set the path instead of a redirect.
Try this, untested
http-request set-path http://preprod.mydomain.com/something/app_a/%[hdr(X-Location-Path)] if app_a_redirection mydomain_domain
Doc link: http-request set-path

How and why is Apache intercepting some CORS requests to Rails?

Before Chrome makes a cross-domain AJAX call it makes an OPTIONS check like this:
curl \
'https://fubar.com/users/sign_in' \
-X OPTIONS \
-H 'Access-Control-Request-Method: POST' \
-H 'Origin: http://snafu.com' \
-H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36' \
-H 'Access-Control-Request-Headers: content-type' \
--compressed \
--insecure \
--verbose
(I added --insecure and --verbose for testing.)
I can see this request in the Apache logs but it doesn't get to Rails.
127.0.0.1 - - [27/Jul/2018:09:22:44 -0400] "OPTIONS /users/sign_in HTTP/1.1" 200 -
If I remove either the Access-Control-Request-Method or Origin headers then it does pass the request to Rails.
Something about the combination of these two headers seems to be causing Apache to handle the request itself and not give Rails a chance to process it.
I am not setting any headers or defining any rewrite rules in the Apache config; it's basically a vanilla install.
I'm not able to find any documentation or configurations explaining why this would be happening and how to prevent it.
1) OPTIONS HTTP call at 'https://fubar.com/users/sign_in' performed from chrome browser with request headers 'Access-Control-Request-Method: POST' and 'Origin: http://snafu.com'
2) the server at 'https://fubar.com/users/sign_in' receives the request
STEP 1
The routing is handles from either nginx or apache webserver which will first apply their own config rules. This settings are included in the file inside /etc/apache2 or /etc/nginx
For example with nginx you can define rules to add_header to the http response or settings to redirect to another url
for example
add_header "Access-Control-Allow-Origin: '*'"
this will add the header "Access-Control-Allow-Origin: '*'" to all responses.
If for example you apply this response to all OPTIONS requests, then all subsequent http request will be whitelisted from any http origin
STEP 2
once the nginx/apache redirection rules are applied, the rails router receives the request and redirects to your controller.
Here you can still add any header you want inside the controller, you can redirect OPTIONS request to a specific controller action, which can add a specific header, be careful to not add twice the same header as that can cause issues.
In this action you can rewrite the Access-Control-Allow-Origin header in the response from the OPTIONS request to whitelist only specific origin domains (you just need to write a routing rule which is applied only to OPTIONS requests)
The origin domain is written in the header of the request
request headers 'Access-Control-Request-Method: POST' and 'Origin: http://snafu.com'

Bypass default caching policy if file is managed by service worker

I am using Google's workbox-cli tool in order to precache some of the files on my website. Is it possible to setup the webserver to return the following in the HTTP response header for all files by default:
cache-control: s-maxage=2592000, max-age=86400, must-revalidate, no-transform, public
But, have the webbrowser use the follwing instead only if the file is going to be precached by the service worker:
cache-control: s-maxage=2592000, max-age=0, must-revalidate, no-transform, public
So, I would like the service worker to change max-age=86400 into max-age=0 in the webserver's response header before precaching the file. This makes the service worker fetch files, that have changed according to the revision in sw.js, from the webserver instead of retrieving them from local cache. Any files not managed by the service worker are cached for 86400 seconds by default.
Some background info
Currently, I am using the following bash script to setup my sw.js:
#!/bin/bash
if [ ! -d /tmp/workbox-configuration ]; then
mkdir /tmp/workbox-configuration
fi
cat <<EOF > /tmp/workbox-configuration/workbox-config.js
module.exports = {
"globDirectory": "harp_output/",
"globPatterns": [
EOF
( cd harp_output && find assets de en -type f ! -name "map.js" ! -name "map.json" ! -name "markerclusterer.js" ! -name "modal.js" ! -name "modal-map.html" ! -name "service-worker-registration.js" ! -name "sw-registration.js" ! -path "assets/fonts/*" ! -path "assets/img/*-1x.*" ! -path "assets/img/*-2x.*" ! -path "assets/img/*-3x.*" ! -path "assets/img/maps/*" ! -path "assets/img/video/*_1x1.*" ! -path "assets/img/video/*_4x3.*" ! -path "assets/js/workbox-*" ! -path "assets/videos/*" ! -path "de/4*" ! -path "de/5*" ! -path "en/4*" ! -path "en/5*" | sort | sed 's/^/"/' | sed 's/$/"/' | sed -e '$ ! s/$/,/' >> /tmp/workbox-configuration/workbox-config.js )
cat <<EOF >> /tmp/workbox-configuration/workbox-config.js
],
"swDest": "/tmp/workbox-configuration/sw.js"
};
EOF
workbox generateSW /tmp/workbox-configuration/workbox-config.js
sed -i 's#^importScripts(.*);$#importScripts("/assets/js/workbox-sw.js");\nworkbox.setConfig({modulePathPrefix: "/assets/js/"});#' /tmp/workbox-configuration/sw.js
sed -i 's/index.html"/"/' /tmp/workbox-configuration/sw.js
uglifyjs /tmp/workbox-configuration/sw.js -c -m -o harp_output/sw.js
On my Nginx webserver the following HTTP header is delivered by default:
more_set_headers "cache-control: s-maxage=2592000, max-age=0, must-revalidate, no-transform, public";
But, if the requested ressource is not handled by the service worker, the default cache-control setting is overwritten:
location ~ ^/(assets/(data/|fonts/|img/(.*-(1|2|3)x\.|maps/|video/.*_(1x1|4x3)\.)|js/(map|markerclusterer|modal|service-worker-registration|sw-registration)\.js|videos/)|(de|en)/((4|5).*|modal-map\.html)) {
more_set_headers "cache-control: s-maxage=2592000, max-age=86400, must-revalidate, no-transform, public";
}
Problem with the current approach (see background info)
I have to keep track of the files and update nginx.confcorrespondingly.
max-age=0 is used also for webbrowsers that don't support service-workers. So, they request the ressources from the webservers on each page visit.
1st Update
My desired precaching behaviour can be illustrated with two of the workbox strategies. I want the service worker to show below behaviour as described in scenario 1 and 2, although cache-control: max-age=86400 is delivered in the HTTP header by the webserver for an asset (e.g. default.js).
Scenario 1: revision in sw.js didn't change
The webpage is accessed, the sw.js file is retrieved from the webserver due to max-age=0 and the webbrowser noticed that the revision for default.js didn't change. In this case, default.js is retrieved from the precache cache:
Scenario 2: revision in sw.js did change
The webpage is accessed, the sw.js file is retrieved from the webserver due to max-age=0 and the webbrowser noticed that the revision of default.js changed. In this case, default.js is retrieved from the webserver:
2nd Update
Basically, the desired strategy is similar to the network-first strategy. But, step 2 is only taken if the revision of the file in sw.js has changed.
3rd Update
If I am not mistaken, there is already some work on this:
self.addEventListener('install', event => {
event.waitUntil(
caches.open(`static-${version}`)
.then(cache => cache.addAll([
new Request('/styles.css', { cache: 'no-cache' }),
new Request('/script.js', { cache: 'no-cache' })
]))
);
});
I don't think you have a comprehensive enough understanding of how service workers actually work.
You define one, or many caches for a service worker to use. You specify what goes in which cache, whether to cache future requests etc
The service worker now intercepts all network requests from the client and then responds to them however you have programmed it to. It can return cached content if available, cached content first while updating over the network, network first and copy to cache in case of no connection, cache for images but not for anything else, only cache GET requests, only cache certain domains, file types etc......
What it caches and for how long each cache is valid is entirely up to you and not influenced by server response headers at all. If you tell your service worker to make a fetch request for a resource then it will load that resource over the network, regardless of any headers or what is already cached locally.
You have total control over the entire caching process, which is very useful but has it's own set of pitfalls.
I used s-max-age instead of s-maxage in the cache-control HTTP header, which lead to some unexpected behaviour with my reverse proxy and workbox service worker. After the fix, the service worker is working as expected.

URL Rewriting with case insensitivity

I want to create URL case insensitive for which I am already using CheckSpelling On and it works fine.
In Parallel I also wished to remove extension from URL for that I applied
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php [NC,L]
It also worked.
But both doesn't work altogether.
If I keep both in htaccess it starts to give error 300 ("Multiple Choices")
You're making it hard on yourself. It'd be easier if you do basic routing in your php. Just send anything to your index.php that's not a directory, and is either not a file or is a php file:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f [OR]
RewriteCond %{REQUEST_FILENAME} (?>.*)(?<=\.php) [NC]
RewriteRule ^(?!index\.php$). index.php [NS,L]
At the top of index.php, do something like this:
<?php
$url = explode('?', $_SERVER['REQUEST_URI'], 2);
$url = substr($url[0], 1);
if ($url) {
$url = strtolower($url) . '.php';
if (preg_match('#^[^./][^/]*(?:/[^./][^/]*)*$#', $url) && file_exists($url)) {
. # does not contain dotfiles, nor `..` directory traversal, so is a php file below web root
include $url;
}
else {
# virtual URL doesn't exist,
# set 404 response code header and serve a default page
include '404.php';
}
exit;
}
# no virtual URL, continue processing index.php
Add a rel=canonical to each page's <head> that contains the lowercase URL (with any query string re-added) so you are not penalized for duplicate content,

URL Rewrite doesn't work

Could you tell me why this rewrite do not pass 2nd value? tt value is passed in to %1 but name is not in to %2
RewriteBase /
RewriteRule ^wedding-hair-and-make-up-images-([^/]*)-(.*)\.php$ franchisee-gallery.php?franchise_name=$1&id_tt=$2 [L]
RewriteCond %{THE_REQUEST} ^(GET|POST|HEAD|TRACE)\ /franchisee-gallery.php
RewriteCond %{QUERY_STRING} name=([^\&]*)
RewriteCond %{QUERY_STRING} tt=(.*)
RewriteRule ^franchisee-gallery.php$ wedding-hair-and-make-up-images-%1-%2.php? [R,L]
The %N refeers to the matching groups of last condition, so %1 is the match of condition:
RewriteCond %{QUERY_STRING} tt=(.*)
http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html#RewriteCond
RewriteCond backreferences: These are backreferences of the form %N (1 <= N <= 9), which provide access to the grouped parts (again, in parentheses) of the pattern, from the last matched RewriteCond in the current set of conditions.
For your case, you could rewrite the access of "franchisee-gallery.php" to another PHP, that makes the redirection ( via HTTP Header Location ). I can't figure it out how to make this via Rewrite. Maybe with PERL External Rewriting Program, using RewriteMap.
Solution founded! Using custom environment variables, it's possible to store the matched values in temporary variables!
RewriteEngine on
RewriteBase /
RewriteRule ^wedding-hair-and-make-up-images-([^/]*)-(.*)\.php$ franchisee-gallery.php?franchise_name=$1&id_tt=$2 [L]
RewriteCond %{REQUEST_URI} ^/franchisee-gallery.php
RewriteCond %{QUERY_STRING} name=([^&]*)
RewriteRule .* - [E=name:%1]
RewriteCond %{REQUEST_URI} ^/franchisee-gallery.php
RewriteCond %{QUERY_STRING} tt=([^&]*)
RewriteRule .* - [E=tt:%1]
RewriteCond %{THE_REQUEST} ^(GET|POST|HEAD|TRACE)\ /franchisee-gallery.php
RewriteRule ^franchisee-gallery.php$ wedding-hair-and-make-up-images-%{ENV:name}-%{ENV:tt}.php? [R,L]

Resources