gorilla mux router handlers - go

I can not get the gorilla mux to work..
When requesting http://www.localhost:9000 this is returned by the web server 404 page not found
But this works http://localhost:9000/ and prints Hello world
package main
import (
"net/http"
"fmt"
"log"
"github.com/gorilla/mux"
)
func Handler(w http.ResponseWriter, r *http.Request){
fmt.Fprint(w, "Hello world")
}
func main(){
r := mux.NewRouter()
r.Host("www.localhost")
r.HandleFunc("/", Handler)
err := http.ListenAndServe(":9000", r)
if err != nil {
log.Fatal("ListenAndServe error: ", err)
}
}

You want to be able to support both localhost and www.localhost
package main
import (
"fmt"
"log"
"net/http"
"github.com/gorilla/mux"
)
func Handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Hello world")
}
func main() {
r := mux.NewRouter()
r.Host("www.localhost").Path("/").HandlerFunc(Handler)
r.HandleFunc("/", Handler)
err := http.ListenAndServe(":9000", r)
if err != nil {
log.Fatal("ListenAndServe error: ", err)
}
}
If you read the documentation carefully, you'll notice that r.Host() is just another pattern matching function. It doesn't set any global rule for that router.
if you want to make that rule to be inherited you'll need to use a subrouter:
subrouter := r.Host("www.localhost").Subrouter()
then you use "subrouter" in place of "r"

Related

How to stop showing target URL in ReverseProxy in Golang using NewSingleHostReverseProxy()?

I am trying to have a reverse proxy in Golang, but I am unable to stop target ip from showing in browser ie. it is simply redirecting to wikipedia (target) rather than showing doing reverseproxy.
Can anyone tell what I am doing wrong?
package main
import (
"net/http"
"net/http/httputil"
"net/url"
"github.com/gorilla/mux"
)
func main() {
target := "https://www.wikipedia.org"
remote, err := url.Parse(target)
if err != nil {
panic(err)
}
proxy := httputil.NewSingleHostReverseProxy(remote)
r := mux.NewRouter()
r.HandleFunc("/forward/{rest:.*}", handler(remote, proxy))
http.ListenAndServe(":8080", r)
}
func handler(ur *url.URL, p *httputil.ReverseProxy) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
r.URL.Host = ur.Host
r.URL.Scheme = ur.Scheme
r.Host = ur.Host
r.URL.Path = mux.Vars(r)["rest"]
p.ServeHTTP(w, r)
}
}

How to add body title to Fprintf output?

I'm trying to add <title>Go</title> to my code example:
package main
import (
"fmt"
"net/http"
"os"
)
func favicon(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "favicon.ico")
}
func sayhelloName(w http.ResponseWriter, r *http.Request) {
hostname, _ := os.Hostname()
fmt.Fprintf(w, "\n\nSystem info:\nHostname [pod name]: %s", hostname)
fmt.Fprintf(w, "\nCurrent URL: %s\n", r.Host)
}
func main() {
http.HandleFunc("/favicon.ico", favicon)
http.HandleFunc("/", sayhelloName)
http.ListenAndServe(":80", nil)
}
I tried to add like:
fmt.Fprintf(w, "<title>Go</title>"). It works but make mess with strings next to. I wouldn't like to use html template only to add title to page. Is there any ways to add title in one string?
not used html template. just used only fmt.Fprintf.
package main
import (
"fmt"
"log"
"net/http"
"os"
)
func favicon(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "favicon.ico")
}
func sayhelloName(w http.ResponseWriter, r *http.Request) {
hostname, _ := os.Hostname()
fmt.Fprintf(w, "<html>")
fmt.Fprintf(w, "<head>")
fmt.Fprintf(w, "<title>%s</title>", "Go")
fmt.Fprintf(w, "</head>")
fmt.Fprintf(w, "<body>")
fmt.Fprintf(w, "<h1>System info: Hostname [pod name]: %s", hostname)
fmt.Fprintf(w, "<h1>Current URL: %s", r.Host)
fmt.Fprintf(w, "</body>")
fmt.Fprintf(w, "</html>")
}
func main() {
http.HandleFunc("/favicon.ico", favicon)
http.HandleFunc("/", sayhelloName)
log.Fatal(http.ListenAndServe(":8080", nil))
}

golang http server send r.URL.Path over socket

I have a http server, and I want to send the r.URL.Path text to a client using a socket
I get a error: undefined: conn in conn.Write
This is becauase conn is defined in another function
What I have tried:
package main
import (
"net"
"io"
"net/http"
)
ln, _ := net.Listen("tcp", ":8081")
conn, _ := ln.Accept()
func hello(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "Hello world!")
conn.Write([]byte(r.URL.Path + "\n")) //Here I'm attemping to send it
}
func main() {
http.HandleFunc("/", hello)
http.ListenAndServe(":8000", nil)
}
Your problem is actually in the way you try to declare variables.
If you want your conn to be on global scope, use var
package main
import (
"io"
"net/http"
"net"
)
var ln, _ = net.Listen("tcp", ":8081")
var conn, _ = ln.Accept()
func hello(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "Hello world!")
conn.Write([]byte(r.URL.Path + "\n")) //Here I'm attemping to send it
}
func main() {
http.HandleFunc("/", hello)
http.ListenAndServe(":8000", nil)
}

"Blank response" NotFoundHandler not working Gorilla

I am trying to debug 404-not-found by writing a custom not-found handler. Here is my code.
package main
import (
"database/sql"
"encoding/json"
"fmt"
"log"
"net/http"
"github.com/coopernurse/gorp"
_ "github.com/go-sql-driver/mysql"
"github.com/gorilla/mux"
)
func main() {
// Create a MUX
r := mux.NewRouter()
http.Handle("/", r)
r.NotFoundHandler = http.HandlerFunc(NotFound)
// Static
r.PathPrefix("/app").HandlerFunc(uiAppHandler)
err := http.ListenAndServe(":8080", nil)
if err != nil {
log.Fatal(err)
}
}
func NotFound(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "custom 404")
}
func uiAppHandler(w http.ResponseWriter, r *http.Request) {
repoFrontend1 := "/UI/KD/WebContent"
http.StripPrefix("/app/", http.FileServer(http.Dir(repoFrontend1)))
}
I am getting a blank response for both existing and non-existing files. I guess NotFound is not getting triggered because of my "/" handler. Then how do I handle notFound for http.Dir?
Here is my directory structure
The response from uiAppHandler is blank because the function does not write to the response w. You should register the file server handler directly with the mux instead of trying to create a handler:
r.PathPrefix("/app").Handler(http.StripPrefix("/app/", http.FileServer(http.Dir(repoFrontend1))))
The mux passes all requests with the prefix "/app" to the handler registered for that prefix. All requests with that prefix are found as far as the mux is concerned. The http.FileServer or whatever you register for that prefix is responsible for generating the 404 response.

How to pass type into an http handler

I'm attempting to separate my http go code into "controllers" by creating a new package for them, but can't figure out how to pass a db type into the handler. I want to be able to pass in the Db type that I create in main.go into my Index handler in index.go. If this is the wrong way to solve this, let me know a better way (I'm learning as I go and would like to keep it simple for now). My code so far:
main.go:
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
"github.com/gorilla/mux"
"log"
"mvc3/app/c"
"net/http"
)
var Db *sql.DB
func main() {
fmt.Println("Starting up!")
var err error
Db, err = sql.Open("mysql", "root#/dev?charset=utf8")
if err != nil {
log.Fatalf("Error on initializing database connection: %s", err.Error())
}
Db.SetMaxIdleConns(100)
err = Db.Ping()
if err != nil {
log.Fatalf("Error on opening database connection: %s", err.Error())
}
r := mux.NewRouter()
r.HandleFunc("/", c.Index)
http.Handle("/", r)
http.ListenAndServe(":8080", nil)
}
/app/c/index.go:
package c
import (
"fmt"
"net/http"
)
func Index(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello world!")
}
Thanks!
use a closure.
in app/c change Index to:
func Index(db *sql.DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// do stuff with db here
fmt.Fprintf(w, "Hello world!")
}
}
then in your main function use it like so: r.HandleFunc("/", c.Index(db))
The Index function returns an anonymous function that fits the the HandleFunc type and also closes over the value of the db that was passed in giving your handler access to that variable.

Resources