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.
Related
My code for a simple file server:
package main
import (
"net/http"
"os"
"github.com/gorilla/handlers"
"github.com/gorilla/mux"
)
func main() {
r := mux.NewRouter()
// default file handler
r.Handle("/", http.FileServer(http.Dir("web")))
// run on port 8080
if err := http.ListenAndServe(":8080", handlers.LoggingHandler(os.Stdout, r)); err != nil {
panic(err)
}
}
My directory structure is:
cmd/server/main.go
web/index.html
web/favicon.ico
web/favicon.png
web/css/main.css
index.html asks for main.css. so when I run go run cmd/server/main.go I get the following output:
127.0.0.1 - - [24/Dec/2019:22:45:26 -0X00] "GET / HTTP/1.1" 304 0
127.0.0.1 - - [24/Dec/2019:22:45:26 -0X00] "GET /css/main.css HTTP/1.1" 404 19
I'm able to see the index.html page, but without the CSS. When I request any other file (e.g. favicon.ico) I also get a 404. Why does my FileServer only serve index.html?
To demonstrate why this does not work consider the following test app:
package main
import (
"fmt"
"net/http"
"github.com/gorilla/mux"
)
type testHandler struct{}
func (h *testHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
fmt.Printf("Got request for %s\n", r.URL)
}
func main() {
r := mux.NewRouter()
hndlr := testHandler{}
r.Handle("/", &hndlr)
// run on port 8080
if err := http.ListenAndServe(":8080", r); err != nil {
panic(err)
}
}
If you run this and access http://127.0.0.1:8080/ in your browser it will log Got request for /. However if you access http://127.0.0.1:8080/foo you will get a 404 error and nothing will be logged. This is because r.Handle("/", &hndlr) will only match on / and not anything below it.
If you change this to r.PathPrefix("/").Handler(&hndlr) then it will work as you expect (the router will pass all paths to the handler). So to fix your example change r.Handle("/", http.FileServer(http.Dir("web"))) to r.PathPrefix("/").Handler( http.FileServer(http.Dir("web"))).
Note: Because this is passing all paths to FileServer there is really no need to use Gorilla Mux; I have left this in on the assumption that you will be using it to add some other routes.
How do I pass http.ResponseWriter in a parameter?
I'm coming from nodejs and would really like to learn Go.
Here is the main file:
import (
"net/http"
"./libs/database"
)
func bla (w http.ResponseWriter, r *http.Request) {
go database.AddFriend("bob", w)
}
Here is database file:
import (
"net/http"
)
func AddFriend (friendName string, w http.ResponseWriter){
fmt.Println(friendName)
w.Write([]byte("Yoooooooo"))
}
Everything works but the w.Write returns nothing to my ajax post.
I'm keep thinking its like nodejs where I can pass an
object then use it. I know its probably something simple but I just can't seem to figure it out.
Don't call database.AddFriend in a goroutine. This is most likely the cause of your problem. By using a goroutine, your connection is closed and response sent, before the output is written to the HTTP response.
func bla (w http.ResponseWriter, r *http.Request) {
database.AddFriend("bob", w)
}
My code looks like this at the moment:
package main
import (
"io"
"net/http"
"fmt"
"net"
)
const (
PORT = ":443"
KEY = "./localhost.key"
CERT = "./localhost.crt"
)
func hello(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "Hello world! :)")
}
func main() {
http.HandleFunc("/", hello)
http.ListenAndServeTLS(PORT, CERT, KEY, nil)
}
What I would like to be able to do is to use the net.Conn that is created when a client reaches my host. The reason behind this is to use golang.org/x/net/http2 in order to create custom frames and edit the transmission of data at a lower level. And for example http2.NewFramer requires a writer and a reader, which I guess would be the actual net.Conn in both cases.
I am pretty to new to Golang so any advice on how to improve myself is well welcomed. Thank you in advance everyone! :)
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.
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