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/
Related
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
I'm using the ESP8266WebServer.h library for the ESP8266. Files can be served to a specific filename by using something like:
...
void example() {
sendFile(200, "text/html", data_example, sizeof(data_example));
}
...
webServer.on ("/example.html", example);
Once a file is served it cannot be updated by executing server.on ("/example.html", example2);.
How can a hosted file be removed (or updated to a blank file) so that it will return a 404 error ?
why not include a conditionnal logic in your example() function in order serve a 404 page when necessary ?
Hope it helps.
I've a simple folder :
Test/
main.go
Images/
image1.png
image2.png
index.html
In main main.go I just put :
package main
import (
"net/http"
)
func main(){
fs := http.FileServer(http.Dir("./Images"))
http.Handle("/Images/*", fs)
http.ListenAndServe(":3003", nil)
}
But when I curl on http://localhost:3003/Images/ or even I add to path file's name, it doesn't work.
I don't understand because it's the same as the reply given on
this subject
Can you tell me so that this does not work ?
You need to remove * and add extra sub-folder Images:
This works fine:
Test/
main.go
Images/
Images/
image1.png
image2.png
index.html
Code:
package main
import (
"net/http"
)
func main() {
fs := http.FileServer(http.Dir("./Images"))
http.Handle("/Images/", fs)
http.ListenAndServe(":3003", nil)
}
Then go run main.go
And:
http://localhost:3003/Images/
Or simply use:
package main
import (
"net/http"
)
func main() {
fs := http.FileServer(http.Dir("./Images"))
http.Handle("/", fs)
http.ListenAndServe(":3003", nil)
}
with:
http://localhost:3003/
The reason the request failed to return what you expected is because they did not match the pattern defined in the http.Handle(pattern string, handler Handler) call. The ServeMux documentation provides a description of how to compose patterns. Any request is prefixed matched from most specific to least specific. It appears as though you have assumed a glob pattern can be used. Your handler would have been invoked with requests to /Images/*<file system path>. You need to define a directory path like so, Images/.
On a side note, it is worth considering how your program gets the directory path to serve files from. Hard coding a relative means your program will only function within a specific location within the filesystem which incredibly brittle. You could use a command line argument to allow users to specify a path or use a configuration file parsed at runtime. These considerations make your program easy to modularize and test.
Dot in ./Images refer cwd current working directory, not you project root. For your server to work you must run it from Test/ directory, or address Images with absolute rooted path.
I am creating a SPA.
I am trying to respond all requests with index.html
(I handle routing on the frontend).
My directory structure look like this:
Backend
-- main.go
Frontend
..(some other files)..
-- index.html
Whole project is located in "C:\Go\Projects\src\github.com\congrady\Bakalarka"
My main.go file looks like this:
package main
import (
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "../Frontend/index.html")
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
When I run my main.go file (using go run), my localhost always responds with "404 page not found".
When I try to serve static content using fmt, everything works fine.
Please help, I'm stuck on this for a really long time and I can't get it to work.
Thanks
Be aware that if you hardcode relative paths in your source file, the directory which you are in when starting the app matters.
In the current configuration, make sure to start the app from the Backend directory, i.e.
C:\Go\Projects\src\github.com\congrady\Bakalarka\Backend,
NOT your apps root directory
C:\Go\Projects\src\github.com\congrady\Bakalarka
or
change the string in the main file to Frontend/index.html and run from
C:\Go\Projects\src\github.com\congrady\Bakalarka
I'm writing a script to download files from urls in a list. The problem I'm having is that the urls don't just point to static files, like file.jpg, they tend to point to servlets that return a file.
What I want to do is download the file for each url and save it with a generic name, then read its headers and rename it with the appropriate extension. (Unless there's a better way)
How could I do that?
I've tried using mime-magic, but it tells me that the extension-less files are directories.
It should work using mime-magic. Are you sure the path is correct and the path is not pointing to a directory?
Otherwise you could use the command line tool file --mime /path/to/file
Here is how to detect an extension of a file using mime-magic:
mime('/path/to/foo.pdf', function (err, type) {
if (err) {
console.error(err.message);
// ERROR: cannot open `/path/to/foo.pdf' (No such file or directory)
} else {
console.log('Detected mime type: %s', type);
// application/pdf
}
});
Note: Added sled's comment as an answer under community-wiki.