golang http server send r.URL.Path over socket - go

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)
}

Related

Output and meaning of PostForm requests in Go

In the code below, I am serving a PostForm request, and when I run the code I am getting an output of Age=20&Name=Mike, instead of a map like {"Name":Mike,"Age":"20"}. Is that output appropriate or am I missing something?
Also what is the difference between a PostForm request and a Post request?
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"net/url"
)
func server() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
content, _ := ioutil.ReadAll(r.Body)
fmt.Println(string(content))
})
log.Fatal(http.ListenAndServe("", nil))
}
func client() {
data := url.Values{}
data.Add("Name", "Mike")
data.Add("Age", "20")
response, err := http.PostForm("http://localhost/", data)
if err != nil {
return
}
defer response.Body.Close()
}
func main() {
go server()
client()
}

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)
}
}

Gorilla sessions cookie usage with a wrapper

I am using a basic wrapper in a web application like this:
package main
import (
"fmt"
"log"
"net/http"
"os"
"github.com/gorilla/mux"
"github.com/gorilla/sessions"
)
const (
PORT = "8083"
)
func navbarWrapper(h http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "header")
h(w, r) // call original function
fmt.Fprintln(w, "footer")
}
}
func main() {
r := mux.NewRouter()
r.HandleFunc("/cookie_write", navbarWrapper(cookie_write))
hostname, _ := os.Hostname()
log.Printf("Listening on port %s https://%s:%s/", PORT, hostname, PORT)
http.ListenAndServe(":"+PORT, r)
}
I would like to set a cookie, but it is not being sent to the browser, but is also not providing an error
var (
key = []byte("16bytestufffffff")
store = sessions.NewCookieStore(key)
)
func cookie_write(w http.ResponseWriter, r *http.Request) {
session, _ := store.Get(r, "session-name")
session.Values["authenticated"] = true
session.Values["stuff"] = "important info"
if err := session.Save(r, w); err != nil {
fmt.Println(err)
fmt.Println("error")
} else {
fmt.Println("worked?")
}
}
If I remove the wrapper, then it works fine and I can see the cookie being generated in the browser:
r.HandleFunc("/cookie_write", cookie_write)
I know I must not be saving the session correctly, but I can't figure out how to do it.

gorilla mux router handlers

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"

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