My code is just the same as in gowiki
package main
import (
"fmt"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
However, after I build and run this program, it exit immediately without blocking so that I get no response when I try to access http://localhost:8080/monkey from Chrome.
Environment: Ubuntu 14(in VirtualBox on Windows7)
Why?
Check the error returned from ListenAndServe
func main() {
http.HandleFunc("/", handler)
fmt.Println(http.ListenAndServe(":8080", nil))
}
http.ListenAndServe function returns an object that conforms error interface. If the call does not block, it definitely means that some kind of error has happened. The most popular are:
there is already another process listening that port
your user has no right to bind socket on port 8080, or 0.0.0.0 interface
In my case, it was a permission denied error. Using sudo worked like a charm.
sudo go run filename.go
or
sudo filename
Related
I'm currently using a basic http.FileServer setup to serve a simple static site. I need to handle 404 errors with a custom not found page. I've been looking into this issue quite a bit, and I cannot determine what the best solution is.
I've seen several responses on GitHub issues along the lines of:
You can implement your own ResponseWriter which writes a custom message after WriteHeader.
It seems like this is the best approach but I'm a bit unsure of how this would actually be implemented. If there are any simple examples of this implementation, it'd be greatly appreciated!
I think this can be solved with your own middleware. You can try to open the file first and if it doesn't exist, call your own 404 handler. Otherwise just dispatch the call to the static file server in the standard library.
Here is how that could look:
package main
import (
"fmt"
"net/http"
"os"
"path"
)
func notFound(w http.ResponseWriter, r *http.Request) {
// Here you can send your custom 404 back.
fmt.Fprintf(w, "404")
}
func customNotFound(fs http.FileSystem) http.Handler {
fileServer := http.FileServer(fs)
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
_, err := fs.Open(path.Clean(r.URL.Path)) // Do not allow path traversals.
if os.IsNotExist(err) {
notFound(w, r)
return
}
fileServer.ServeHTTP(w, r)
})
}
func main() {
http.ListenAndServe(":8080", customNotFound(http.Dir("/path/to/files")))
}
I am fairly new to Backbone and Go and trying to call a function depending on URL.
This is my code in Router from where a request is going to a Go page.
collection.fetch({
url: "/bands"
})
.done(function(data) {
console.log("hello");
});
This is my code in which I am handling all the request:
func viewHandler(w http.ResponseWriter, r *http.Request) {
fmt.println("in viewHandler")
}
func main() {
http.Handle("/", http.FileServer(http.Dir("../")))
http.HandleFunc("/bands", viewHandler)
http.ListenAndServe(":8080", nil)
}
In my Network tab the header is:
Request URL:http://localhost:8080/bands
Request Method:GET
Status Code:200 OK
Remote Address:[::1]:8080
But nothing is getting printed on console since I guess viewHandler is not getting called. What is the reason for this?
Actually your code is fine... that means almost fine. fmt.println() needs a capital "P":
func viewHandler(w http.ResponseWriter, r *http.Request) {
fmt.Println("in viewHandler")
}
When I test your code with this adjustment it prints "in viewHandler" to the terminal as expected.
I want to perform a get operation. I am passng name as a resource to the URL.
The URL I am hitting in Postman is : localhost:8080/location/{titan rolex} ( I chose the GET method in the dropdown list)
On the URL hit in Postman, I am executing the GetUser func() with body as:
func GetUser(rw http.ResponseWriter, req *http.Request) {
}
Now I wish to get the resource value i.e 'titan rolex' in the GetUser method.
How can I achieve this in golang?
In main(), I have this :
http.HandleFunc("/location/{titan rolex}", GetUser)
Thanks in advance.
What you are doing is binding the complete path /location/{titan rolex} to be handled by GetUser.
What you really want is to bind /location/<every possible string> to be handled by one handler (e.g. LocationHandler).
You can do that with either the standard library or another router. I will present both ways:
Standard lib:
import (
"fmt"
"net/http"
"log"
)
func locationHandler(w http.ResponseWriter, r *http.Request) {
name := r.URL.Path[len("/location/"):]
fmt.Fprintf(w, "Location: %s\n", name)
}
func main() {
http.HandleFunc("/location/", locationHandler)
log.Fatal(http.ListenAndServe(":8080", nil))
}
Note however, more complex paths (such as /location/<every possible string>/<some int>/<another string>) will be tedious to implement this way.
The other way is to use github.com/julienschmidt/httprouter, especially if you encounter these situations more often (and have more complex paths).
Here's an example for your use case:
import (
"fmt"
"github.com/julienschmidt/httprouter"
"net/http"
"log"
)
func LocationHandler(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
fmt.Fprintf(w, "Location: %s\n", ps.ByName("loc"))
}
func main() {
router := httprouter.New()
router.GET("/location/:loc", LocationHandler)
log.Fatal(http.ListenAndServe(":8080", router))
}
Note that httprouter uses a slightly different signature for handlers. This is because, as you can see, it passes these parameters to the functions as well.
Oh and another note, you can just hit http://localhost:8080/location/titan rolex with your browser (or something else) - if that something else is decent enough, it will URLEncode that to be http://localhost:8080/location/titan%20rolex.
I try to switch from HTTP to HTTPS:
func handler(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Content-Type", "text/plain")
w.Write([]byte("This is an example server.\n"))
}
func main() {
http.HandleFunc("/", handler)
log.Printf("About to listen on 8080. Go to https://127.0.0.1:8080/")
err := http.ListenAndServeTLS(":8080", "cert.pem", "key.pem", nil)
if err != nil {
log.Fatal(err)
}
}
And I am getting the following error:
crypto/tls: failed to parse key PEM data
My application is running in HTTP mode now and I want it to run in HTTPS mode.
Can anyone suggest how to make it work in HTTPS?
The error indicates that the key.pem file cannot be parsed (could be invalid or lacking permission to read its content). Make sure the file is valid and sufficient permissions are set.
For testing purposes, use the generate_cert.go in the crypto/tls package to generate valid cert.pem and key.pem files.
To generate, run the following command (windows):
go run %GOROOT%/src/crypto/tls/generate_cert.go -host="127.0.0.1"
Linux:
go run $GOROOT/src/crypto/tls/generate_cert.go -host="127.0.0.1"
I have this simple program:
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/users", UsersHandler)
fmt.Println("Starting server...")
http.ListenAndServe(":8181", nil)
}
func UsersHandler(w http.ResponseWriter, r *http.Request) {
fmt.Println("Users")
}
If I send a GET command from the browser: http://localhost:8181 I can see the message "Users" printed, but If I connect from telnet no message is printed when I do:
telnet 127.0.0.1 8181
GET /users HTTP/1.1
Any idea why is that ?
You need to enter a second carriage return, which signifies the end of the headers block.