So I have this weird issue where some routes will work and others won't. I will first show you my main function and then give examples of what the problem is.
func main() {
http.HandleFunc("/", home)
http.HandleFunc("/project", project)
http.HandleFunc("/about", about)
http.HandleFunc("/contact", contact)
http.Handle("/resources/", http.StripPrefix("/resources", http.FileServer(http.Dir("./assets"))))
err := http.ListenAndServe(":80", nil)
if err != nil {
fmt.Println("ListendAndServe doesn't work : ", err)
}
}
For example, the route "/contact/" does not work, when I run this code and go to localhost/contact it will send me to the homepage. However when I change the route in the Handlefunc to "/contactos" and then go to localhost/contactos it does work.
Another example, "/project" works now, but when I change it to "/projects" it does not.
Note that if you register /project/ (note the trailing slash), then both /project/ and /project will work (with or without trailing slash). If you register /project (without a trailing slash), then only /project will work, /project/ will be matched by the root handler /.
Quoting from http.ServeMux:
If a subtree has been registered and a request is received naming the subtree root without its trailing slash, ServeMux redirects that request to the subtree root (adding the trailing slash). This behavior can be overridden with a separate registration for the path without the trailing slash. For example, registering "/images/" causes ServeMux to redirect a request for "/images" to "/images/", unless "/images" has been registered separately.
See related questions:
How to map to the same function with a pattern that ends with or with "/" with http.HandleFunc
Related
I have a Nginx + app in laravel. Right now it is working fine, but I need to show some important announcements to users - so I just create a simple index.html file.
How to setup Nginx to behave as follows:
when the user type "main URL" - example.org just display a static HTML with the temporary announcement
when the user types URL to something on the page - example.org/something - then just show him laravel app
Update # 2022.05.22
The following solution is not workable if the requested URI ends with a slash (which is exactly the case when a root request GET / HTTP/<version> is made). The reason is the index module (which is called before the static module) see that request URI ended with slash, checks it for being a directory and returns an error if it isn't. The right solution is to rewrite the URI to make it not ended with a slash, and provided below the not working one.
Not working
You can use an "exact match" location:
server {
...
location = / {
alias /full/path/to/your/stub.html;
}
# rest of the config remains as it was
location / {
...
}
location ~ \.php$ {
...
}
...
}
Using an alias directive you can specify any HTML file from any directory on your server no matter what your root directive is set to.
Working
location = / {
root /path/to/static; # needed only if the path differs from the global root
rewrite ^ /stub.html break;
}
I created a project, where I have:
my-project.com to show my Angular 8 App
api.my-project.com to access my Symfony 5 API
I built a very basic landing page on my Angular app, but now, I changed my mind and I want to have my angular app into app.my-project.com and keep the my-project.com to show a beautifull landing page.
The problem is that there are some clients that are already using the service on the main domain, and that request should be redirected to the app.my-project.com subdomain.
Should be something like this:
my-project.com/login -> app.my-project.com/login
my-project.com/pm-something -> app.my-project.com/pm-something
Here is a pseudocode of what I need:
if( url.includes('login') or url.includes('pm-') ) {
redirectTo(app.my-project.com)
}
I thought the easiest way to achieve that is to rewriting the routes in my NGINX config file, but I am not sure the correct way to do it.
Thanks in advance.
NGINX chooses request URI processing rules according to defined location blocks within the server configuration. Official documentation on this directive is here, and here are some additional explanations. You can achieve desired behavior using two prefix locations:
location /login {
return 301 $scheme://app.my-project.com$request_uri;
}
location /pm- {
return 301 $scheme://app.my-project.com$request_uri;
}
This two prefix locations could be replaced by a single regex matching location:
location ~ ^/(login|pm-) {
return 301 $scheme://app.my-project.com$request_uri;
}
NGINX uses system PCRE library and the general PCRE regex syntax, except you should not use delimiter characters for regex patterns (matching against a regex specified using ~ (case-sensitive matching), ~* (case-insensitive matching) or !~/!~* (case-sensitive/case-insensitive non-matching) operators). Additionally you are not required to prefix / character with a backslash (although you still can do it, it won't change the regex pattern meaning).
Hello awesome stackoverflow community,
Apologies for the lame question.
I've been playing around with the net/http package in Go, and was trying to set an http.Handle to serve the contents of a directory. My code to the Handle is
func main() {
http.Handle("/pwd", http.FileServer(http.Dir(".")))
http.HandleFunc("/dog", dogpic)
err := http.ListenAndServe(":8080", nil)
if err != nil {
panic(err)
}
}
My dogpic handler is using os.Open and an http.ServeContent, which is working fine.
However, when I try to browse localhost:8080/pwd I am getting a 404 page not found, but when I change the pattern to route to /, as
http.Handle("/", http.FileServer(http.Dir(".")))
it is showing the contents of the current page. Can someone please help me figure out why the fileserver is not working with other patterns but only /?
Thank you.
The http.FileServer as called with your /pwd handler will take a request for /pwdmyfile and will use the URI path to build the filename. This means that it will look for pwdmyfile in the local directory.
I suspect you only want pwd as a prefix on the URI, not in the filenames themselves.
There's an example for how to do this in the http.FileServer doc:
// To serve a directory on disk (/tmp) under an alternate URL
// path (/tmpfiles/), use StripPrefix to modify the request
// URL's path before the FileServer sees it:
http.Handle("/tmpfiles/", http.StripPrefix("/tmpfiles/", http.FileServer(http.Dir("/tmp"))))
You'll want to do something similar:
http.Handle("/pwd", http.StripPrefix("/pwd", http.FileServer(http.Dir("."))))
you should write http.Handle("/pwd", http.FileServer(http.Dir("./")))
http.Dir references a system directory.
if you want localhost/ then use http.Handle("/pwd", http.StripPrefix("/pwd", http.FileServer(http.Dir("./pwd"))))
it will serve all you have into /pwd directory at localhost/
I have a thumbnail class and it accepts external hosts too. It works like this right now :
http://mysite.com/resize/src=http://google.com/logo.png&w=50&h=50
I want to make it clean url with my "resize.mysite.com" subdomain like this :
http://resize.mysite.com/400x200/http://google.com/logo.png
I almost done it with this rewrite rule :
rewrite ^/([^x]*)x([^/]*)/(.*)$ /resize.php?w=$1&h=$2&src=$3 last;
But it's sending "src" without second slash after "http:" and it causes to resize class error, like this :
http:/google.com/logo.png
http://google.com/logo.png (what I expect)
How this can be fixed?
The first thing comes in mind is that your are using somewhere in your nginx configuration file special directive merge_slashes, is it true? If yes and your are using merge_slashes on then all your requests with double or triple and so on slashes will comes as one slash.
Can it be a solution to your problem to set directive merge_slashes off ?
I have this config that works as expected in an empty server { } definition
location ^~ /foo/ {
alias /var/www/foo/;
}
But when I move this in a considerably bigger server definition (one used for a WordPress multi-site config), it will stop working and wordpress will respond to it (which obviously was not my intent).
I tried to put at the begining or end of server block, but this didn't change it.
How can I force Nginx to use this location?
You are probably looking for break.
location ^~ /foo/ {
alias /var/www/foo/;
break;
}
From the HttpRewriteModule documentation:
last - completes processing of current rewrite directives and
restarts the process (including rewriting) with a search for a match
on the URI from all available locations.
break - completes processing of current rewrite directives and
non-rewrite processing continues within the current location block
only.
Note that outside location blocks, last and break are effectively the
same.
Location blocks in Nginx are exclusive. If you use location ^~ then other rules probably expiry headers for static objects will not apply unless you copy those rules as nested under the same location block.
If you could share your full config then I can make it work for you. Most likely you need to use nested location blocks.
location = /aliasname/ {
alias /path/to/alias/
}
Trailing slash will be a problem if it is not present in URI.
See https://www.digitalocean.com/community/tutorials/understanding-nginx-server-and-location-block-selection-algorithms#matching-location-blocks