Directory listing wrong links in golang http.FileServer() - http

I'm using http.FileServer in Go to serve some static file into a directory.
This is how I map it using mux as a router:
r.PathPrefix("/download").Handler(http.StripPrefix("/download", http.FileServer(http.Dir(dirPath)))).Methods("GET")
where dirPath is an absolute path of a directory in my file system.
Now it seems to work fine when asking the directory listing with localhost:8080/download, because it returns a page like this
<pre>
a.xml
b.zip
</pre>
Unfortunately the links are broken because I expect them to be mapped, for example to localhost:8080/download/a.xml , while file server maps them to localhost:8080/a.xml.
How can I make my directory listing keep the /download path prefix in links?

The problem is the pattern you register you handler with: "/download".
There are 2 problems with it:
The generated URLs are wrong because the handler returned by the http.FileServer() function generates relative URLs to files and subfolders; relative to the root folder passed to http.FileServer(), and if your page is available under the path /download, a relative URL like href="a.xml" will be resolved to /a.xml, and not to /download/a.xml.
Even if the URLs would be good, the files would not be served as the requests would not get routed to your handled (to the file server handler). You must add a trailing slash, as "/download" only matches this single path, and not all paths starting with it. Add a trailing slash: "/download/" and it will match the rooted subtree /download/*.
So the solution is:
r.PathPrefix("/download/").Handler(
http.StripPrefix("/download", http.FileServer(http.Dir(dirPath))),
).Methods("GET")
This is documented at http.ServeMux:
Patterns name fixed, rooted paths, like "/favicon.ico", or rooted subtrees, like "/images/" (note the trailing slash).
Note that even though we're now using the "/download/" registered path, users are not required to type the trailing slash in the browser, as leaving that out the server will send a redirect to the path that ends with a trailing slash. This will happen automatically. This is also documented at 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.
Read related question: Go web server is automatically redirecting POST requests
Here's a simple file server app using only the standard library:
http.Handle("/dl/",
http.StripPrefix("/dl", http.FileServer(http.Dir("/home/bob/Downloads"))),
)
panic(http.ListenAndServe("localhost:8080", nil))

Related

Nginx Rewrite URL Rule having special character(#) for Page section

I need help in rewriting the URL in nginx configuration which should work as below :
/products/#details to /produce/#items
but it is not working as # is creating a problem.
Note : # in the URL denotes the page section
e.g. www.test.com/products/#details should get redirected to www.test.com/produce/#items
This is impossible using nginx because browsers don't send hashtags (#details) to servers. So you cannot rewrite in nginx or any other web servers.
In other words, hashtags is available to the browser only, so you have to deal it with Javascript. The server can not read it.
https://www.rfc-editor.org/rfc/rfc2396#section-4
When a URI reference is used to perform a retrieval action on the identified resource, the optional fragment identifier, separated from the URI by a crosshatch ("#") character, consists of additional reference information to be interpreted by the user agent after the retrieval action has been successfully completed. As such, it is not part of a URI, but is often used in conjunction with a URI.
There is no way to do this rewrite. The # and everything that precedes it will not be sent to the server, it is completely handled on the client side.

Get 301 status code when sending GET request with parameter

I have a very simple Go server code setup with mux and when I use curl with GET request params (localhost:8080/suggestions/?locale=en), I get 301 status code (Move permanently). But when there's no get parameters, it's working just fine.
func main() {
router := mux.NewRouter().StrictSlash(true)
router.HandleFunc("/suggestions", handleSuggestions).Methods("GET")
log.Fatal(http.ListenAndServe("localhost:8080", router))
}
Can somebody shed me a light on this.Thanks
go doc mux.StrictSlash states:
func (r *Router) StrictSlash(value bool) *Router
StrictSlash defines the trailing slash behavior for new routes. The initial
value is false.
When true, if the route path is "/path/", accessing "/path" will redirect to
the former and vice versa. In other words, your application will always see
the path as specified in the route.
When false, if the route path is "/path", accessing "/path/" will not match
this route and vice versa.
Special case: when a route sets a path prefix using the PathPrefix() method,
strict slash is ignored for that route because the redirect behavior can't
be determined from a prefix alone. However, any subrouters created from that
route inherit the original StrictSlash setting.
So to avoid the redirects you can either mux.NewRouter().StrictSlash(false) which is equivalent to mux.NewRouter() or use a URL with a trailing slash i.e. router.HandleFunc("/suggestions/", handleSuggestions).Methods("GET")
That's simply because you registered the path /suggestions (note: there is no trailing slash), and you call the URL localhost:8080/suggestions/?locale=en (there is a trailing slash after /suggestions).
You router detects that there's a registered path which would match the requested path without the trailing slash (based on your Router.StrictSlash() policy), so it sends a redirect which when followed would lead you to a valid, registered path.
Simply use a URL without trailing slash after suggestions:
localhost:8080/suggestions?locale=en

Different static files for the same path but different domains on App Engine

I'm running WordPress Network with custom domains on Google App Engine Standard Environment (so I can't use nginx or something).
What I want to do is to serve different static content for different domains but using the same path:
somedomain1.com/favicon.ico ----> static/somedomain1.com/favicon.ico
somedomain2.com/favicon.ico ----> static/somedomain2.com/favicon.ico
somedomain3.com/favicon.ico ----> static/somedomain3.com/favicon.ico
etc…
I tried to use domain names in app.yaml URL handlers, but it ain't work for me:
handlers:
- url: (http|https)://somedomain1.com/favicon.ico
static_files: static/somedomain1.com/favicon.ico
upload: static/somedomain1.com/favicon.ico
Is this possible by means of the standard environment of App Engine?
You cannot use the app.yaml URL routing for such purpose because the handler url configuration doesn't apply to the host/domain name portion of the URL, it only applies to the file path portion. From the url row in the Handlers element table (emphasis mine):
url
Required element under handlers. The URL pattern, as a regular
expression. The expression can contain groupings that can be referred
to in the file path to the script with regular expression
back-references. For example, /profile/(.*)/(.*) would match the URL
/profile/edit/manager and use edit and manager as the first and second
groupings.
In other words this portion of your configuration is not really valid:
url: (http|https)://somedomain1.com/favicon.ico`
You could complement your WordPress static offering with a small app which could take care of dynamically selecting a particular artifact based on the domain in the request's URL.

Parse url to get a string in Nginx

I have a web server sitting behind Nginx. If there is an error, then I want to fetch some information from the url and pass it on to a static file as parameters. I have configured Nginx to fetch the url parameters from the url using $arg_param_name. However, I also need to fetch a String from the url path itself. So if the url is as below:
www.website.com/path1/path2?arg1=val&arg2=someval
Now, how can I parse this url to fetch the last path (path2 in this case)? My location directive is as below:
location ~*/path1/{
...
}
The url need not always have the same number of paths. It can also have 3 paths. So I can't use $1, $2 etc. I need to fetch the last path, i.e the path which is immediately followed by the url parameters (the ? symbol).

HTTP PUT for new file creation and directory creation

How would a HTTP Server differentiate whether the request in PUT is for a folder creation or a file creation in a directory.
For HTTP GET what I understood is, if the URL has a trailing /, then HTTP Server looks out for a folder with that name and, if does not exist can look out for a file.
How does this work for PUT for a new file and folder creation?
HTTP (the protocol) doesn't have any concept of files or folders. URIs are opaque, except when a relative URI reference is resolved against a base URI.
If you want your server to provide file/folder services, you may want to look into WebDAV (RFC 4918).

Resources