For the code examples in the firebase docs, it says to initiate a url rewrite like so:
"hosting": {
// Add the "rewrites" section within "hosting"
"rewrites": [ {
"source": "**",
"destination": "/index.html"
} ]
}
What do I do when I want to pass a parameter to the index page? I tried:
"hosting": {
// Add the "rewrites" section within "hosting"
"rewrites": [ {
"source": "/item/**",
"destination": "/item.html?i=$1"
} ]
}
But that doesn't do anything..
I have also tried the answer below:
"hosting": {
// Add the "rewrites" section within "hosting"
"rewrites": [ {
"source": "/item/:item",
"destination": "/item.html?i=:item"
} ]
}
but that just returns a 404 page.
I know this is an old question but I had a similar issue and didn't find an answer so thought I'd share how I solved it.
{
"hosting": {
// Add the "rewrites" section within "hosting"
"rewrites": [ {
"source": "/item/**",
"destination": "/item.html"
} ]
}
I solved my issue by rewriting the dynamic URL to the static html page. Since it's a rewrite the URL will stay as the source URL pattern and not change to the destination URL like a redirect would.
We can then read the source URL through window.location.pathname with Javascript on the item.html page. You can then use .split('/') to return an Array to choose the part that you need.
Hope this helps to anybody looking for a similar solution.
I have just received an email from Firebase support with the follwing:
Update From Firebase support:
Your use case is not possible with Firebase Hosting alone. You will need to make use of Cloud Functions as well to do so. Firebase has just recently released a native Firebase Hosting + Functions integration which makes it possible to perform server-side processing so you can redirect URLs to a function where you can write code to dissect the path and generate whatever response you want. You may check our documentations out to know more about it in detail.
https://firebase.google.com/docs/hosting/functions
I have emailed them back to see if this is something that will be added in the future as it seems a little overkill to run to processes for one page.
Update 28/07/2017
Since this is not supported, I have filed a feature request for you. However, I am not able to share any details or timelines for now. We'll keep your feedback in consideration moving forward though.
In the meantime, you may keep an eye out on our release notes.
Have a great day.
https://firebase.google.com/support/releases
I ran into this same issue as well. Although this isn't possible with rewrites, I found it is possible with redirects:
"redirects": [
{"source": "/user/friendly/url.html",
"destination": "/userunfriendly.html?myid=42",
"type": 301
},
"hosting": {
// Add the "rewrites" section within "hosting"
"rewrites": [ {
"source": "/item/:item",
"destination": "/item.html?i=:item"
} ]
}
Give that a try.
FireBase Allows for Static web hosting. It also has some Custom Behaviours
https://firebase.google.com/docs/hosting/url-redirects-rewrites
Redirects:: this is only for page forwarding
Rewrites:: when you want to show the same content for multiple URLs [ it is there for URL reversing ].
It also provides control over the MIME types of the HTTP requests.
Now, from the Question above I see you are trying to Query for a DOM object from the page which is what Dynamic web hosts provide.
https://www.quora.com/How-are-dynamic-websites-hosted-1
Related
I have a monorepo with two projects - web and docs. Each of these is their own Vercel project with the web project mounted at https://example.com and docs mounted at https://docs.example.com. All of this works as expected.
I now want to have the docs project be available at https://example.com/docs. In the web project, I setup the following rewrites in my vercel.json file.
{
"rewrites": [
{
"source": "/docs/:match*",
"destination": "https://docs.example.com/:match*"
},
{ "source": "/(.*)", "destination": "/" }
]
}
This works for the main index file, but all of the corresponding css and js files result in 404's. The browser is looking for those files at https://example.com/_next which isn't correct, it should be looking at https://docs.example.com/_next.
How do I make this work?
rewrite vs. redirect
Let's first understand this difference.
A rewrite is something that happens on the server only. The server will rewrite the URL that has been requested and search for content of that rewritten URL. The client will not know anything about that. E.g. if /a.html is rewritten to /b.html, the client will receive the same content on both URLs. Client won't know, if there is the same file two times or if one (or both) requests have been rewritten to some other resource.
A redirect on the other hand side involves the client (i.e. browser). If the server is asked for an URL that should be redirected, it will reply back to the client/browser with the destination URL of the rewrite. The client will then send another request for the new URL and make this visible to the end user by changing the address in the navigation bar. If /a.html is redirected to /b.html, the client will not receive the actual content of b.html when requesting a.html, but the browser will update the address to b.html and send a new request.
What's the issue with rewrites in your case?
The HTML contains references to other resources using absolute paths, e.g. something like:
<script src="/_next/static/..."></script>
If this file should be served as docs.example.com and example.com/docs (e.g. using rewrites), the actual HTML will not change. The browser will thus try to access docs.example.com/_next/static/... or example.com/_next/static/... respectively. That works for the first case (docs.example.com), but not for the second one. You've noticed that already.
You can change the basePath of next, e.g. to /docs. Then the HTML would contain <script src="/docs/_next/...">. That would make the browser request docs.example.com/docs/_next/... or example.com/docs/_next/... respectively. That would work for the second case, but not the first one. You could heal the first case with more rewrite rules, but I'd suggest a KISS solution.
Now what?
As mentioned in the comments, placing the exact same content at two different addresses is not good practice. And you can see, that is is causing subsequent difficulties as well. (Not to mention punishment by search engines for duplicate content.)
A good solution would be to decide where to store the content. That should be either docs.example.com or example.com/docs, not both.
Using docs.example.com, forwarding example.com/docs/ to docs.example.com
I'd suggest (and assume in this section) to take docs.example.com to have a clear separation of concerns.
So in Vercel you would set up two projects. One for your "main" next instance, another one for the "docs" next instance. (Both can come from the same repo, that doesn't matter.)
You then assign domains to both projects, e.g. www.example.com to the "main" project, docs.example.com to the "docs" project.
example.com as well as docs.example.com should be working right now.
example.com/docs/ should yield a 404 error.
Then you add redirects (not rewrites!) for your "main" project by adding a vercel.json like this:
{
"redirects": [
{ "source": "/docs/:path*", "destination": "https://docs.example.com/:path*" }
]
}
Now, if you enter example.com/docs/foo in your browser, you should be redirected to docs.example.com/foo and the page should load properly.
Using only example.com/docs/
If you decide to have the docs content only at example.com/docs/, the solution would be as follows:
Add basePath: '/docs' to next.config.js of the docs next project. Do not add a domain to this vercel project.
In the "main" next project add a vercel.json with a rewrite like this:
{
"rewrites": [
{ "source": "/docs", "destination": "https://$domain-of-docs-project.vercel.app/docs" },
{ "source": "/docs/:path*", "destination": "https://$domain-of-docs-project.vercel.app/docs/:path*" }
]
}
Please comment, if you have additional questions or this doesn't fix the issue.
I think you can use the vercel.json like this:
{
"rewrites": [
{
"source": "/:path*",
"has": [
{
"type": "host",
"value": "docs.example.com"
}
],
"destination": "/docs/:path*"
}
]
}
Next offers a specific example for this.
Your "web" project should handle rewrites, as seen here.
next.config.js:
const { DOCS_URL } = process.env //this should be the vercel URL NOT docs.example.com
/** #type {import('next').NextConfig} */
module.exports = {
async rewrites() {
return [
{
source: '/:path*',
destination: `/:path*`,
},
{
source: '/docs',
destination: `${DOCS_URL}/docs`,
},
{
source: '/blog/:path*',
destination: `${BLOG_URL}/docs/:path*`,
},
]
},
}
Your "docs" app needs to set a base path, as seen here. next.config.js:
module.exports = {
basePath: '/docs',
}
Then to ensure that docs.example.com no longer serves the docs as well, I'd just remove the DNS record. Instead you'll just have a vercel URL that you will use in the rewrites in "web". No need to point to that server from docs.example.com.
Nextjs documentation for multi-zone
Nextjs example with multi-zones
We are trying to build a REST api using firebase functions. We want that format because we are a web services company who need to expose an api to our clients. People are mostly familiar with REST, therefore, REST.
Following the advice given here I have layered a custom domain in front of a firebase function. I did this by first forwarding my custom domain to the firebase domain via an A record,then setting up a rewrite for the hosting:
"hosting": {
"public": "public",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "/api/**",
"function": "api"
},
{
"source": "!/#(api)/**",
"destination": "/index.html"
}
]
},
Note that the api function is mapped to anything going to /api/. So far so good. Now I want to make a POST request with a body to mydomain.com/api/user. Unfortunately, when doing so, I get a response Cannot GET /api/user. It seems like firebase is converting the request into a GET before it reaches the function at api. Does anyone know how to make POST requests to functions behind custom domains?
In case someone stumbles over this it's because our route was not defined as containing api. We had something like /user but this configuration obviously requires /api/user.
I have an api set up on Google Cloud Functions (https://europe-west1-myproject-name.cloudfunctions.net/api/v1/ical.ics).
This works well, but I wish to set up a "friendly" domain name for the api. :)
According to Googles documentation this is seems easy, but it does not seem to work for cloud functions outside the USA, eg. europe-west1.
I have updated the firebase.json file with the below code according to documentation.
"hosting": {
"public": "public",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "/api/**",
"function": "api"
},
{
"source": "**",
"destination": "/index.html"
}
]
}
When accessing https://myproject-name.web.app/api/v1/ical.ics
I get redirected to https://us-central1-myproject-name.cloudfunctions.net/api/api/v1/cal.ics with error 403 and the below error message.
Error: Forbidden
Your client does not have permission to get URL /api/api/ical.ics from this server.
I must be overlooking something really basic here, since this seems like a really easy operation? :)
Kind regards
/K
As stated in the documentation (see blue text block):
If you are using HTTP functions to serve dynamic content for Firebase
Hosting, you must use us-central1.
You will also find a similar warning in the doc you refer to in your question about "Serve dynamic content and host microservices with Cloud Functions" (See blue text block as well):
Firebase Hosting supports Cloud Functions in us-central1 only.
It is not completely the answer you are looking for since it is not possible with Firebase Hosting.
But it is possible to get a custom domain in front of your cloud functions hosted in EU by using Cloud Run.
I followed this guide:
https://cloud.google.com/endpoints/docs/openapi/get-started-cloud-functions
And after that i added the custom domain under the Manage custom domains on Cloud Run.
Is there a way to use a custom domain for firebase cloud functions http hooks.
The default url for cloud functions looks something like this:
https://us-central1-my-awesome-app.cloudfunctions.net/ios-oauth/
And
I would like to make it look like this:
https://myawesomeapp.com/ios-oauth/
I looked around if there was some other people looking for the same solution and sure enough I found this:
https://stackoverflow.com/questions/43482224/firebase-cloud-functions-custom-domain
I have contacted firebase support to get some answers about this.
And I was forwarded to this part in the documentation.
https://firebase.google.com/docs/hosting/functions#create_an_http_function_to_your_hosting_site
You can use your own domain with the firebase-cloud-functions. The way to do is is using the firebase-hosting.
Connect custom domain to firebase hosting
Add custom function routing to firebase.json
{
"hosting": {
"public": "public",
// Add the following rewrites section *within* "hosting"
"rewrites": [{
"source": "/bigben", "function": "bigben"
}]
}
}
Deploy to firebase
The accepted answer is correct, and I created this repository last year to demonstrate the functionality: https://github.com/cjmyles/firebase-react-express
In order to retain the HTML pushState functionality as per https://firebase.google.com/docs/hosting/full-config#rewrites you may want to extend the rules to allow all other requests through to your index.html page, which solves the issue #Boris was facing in his answer.
"rewrites": [
{
"source": "/api/**",
"function": "app"
},
{
"source": "!/#(api)/**",
"destination": "/index.html"
}
]
This shouldn't really be needed as the rewrite rules are meant to match the first occurence of a request (so the order matters), but this worked for me by allowing all non-api related requests through.
Please note: At the time of writing this the Firebase documentation states: Firebase Hosting supports Cloud Functions in us-central1 only.
If anyone else runs into this, Thomas Bulva's answer is correct but for me, I also had to remove the below snippet from the firebase.json file. .
It was redirecting any request to the index.html page. My https://us---<>.cloudfunctions.net URL was working fine; when I did /helloWorld it would take me to "Hello from Firebase!" But if I tried the same from my custom domain, it would fail. Removing this fixed it.
{
"source": "**",
"destination": "/index.html"
},
While attempting to get CORS working with Cloud Functions for Firebase, I tried to follow the official example here: https://github.com/firebase/functions-samples/tree/master/authorized-https-endpoint
However, even following the tutorial instructions as exactly as possible, I still get this error in the console:
I never got CORS working, but the workaround I found was to use hosting redirects for the functions. That way, HTTP function calls are not cross site at all.
https://firebase.google.com/docs/hosting/functions (See "Direct Hosting requests to your function")
{
"hosting": {
"public": "public",
// Add the following rewrites section *within* "hosting"
"rewrites": [ {
"source": "/api/bigben", "function": "bigben"
} ]
}
}
Note: I have to define a redirect for every endpoint. Is there a way to have general rewrites? e.g.
"source": "/api/*", "function": "*"
Try following this ?
https://stackoverflow.com/a/42756623/6650162
Handling CORS in Google Cloud Functions
Hope that helps!