newbie compilation error net/http Response - http

Why do I get a compilation error for this code? Response type is defined in "net/http"
package main
import "net/http"
func main() {
}
func GetWithProxy(urlString string, proxyString string) (resp *Response, err error) {
return nil, nil
}
error:
.\t.go:3: imported and not used: "net/http"
.\t.go:7: undefined: Response

It's complaining that you didn't use net/http, which you didn't.
package main
import "net/http"
func GetWithProxy(urlString string, proxyString string) (resp *http.Response, err error) {
return nil, nil
}
func main() {
}
This will compile because now you are using net/http. The compiler didn't know you were talking about net/http's Response type.
If you want 'absorb' net/http's namespace you can do:
package main
import . "net/http"
func GetWithProxy(urlString string, proxyString string) (resp *Response, err error) {
return nil, nil
}
func main() {
}
Observe:
https://play.golang.org/p/WH1NSzFhSV

Related

Golang FileServer check progress

I have created a simple FileServer using GoLang
package main
import (
"log"
"net/http"
)
func loggingHandler(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log.Println(r.Method, r.RemoteAddr,r.URL.Path)
h.ServeHTTP(w, r)
})
}
func main() {
http.ListenAndServe(":8080", loggingHandler(http.FileServer(http.Dir("/directory/subdir/"))))
}
Now I am looking for a way to check if file is properly downloaded by host, or monitor how many bytes are arleady downloaded.
Unfortunetly I am unable to find any hints on the internet or if it is even posibble.
Has anyone encountered a similar problem? Is it possible to verify the correctness of downloading the file from the server?
You can provide your implementation of FileSystem with a progress counter to the FileServer.
Example:
package main
import (
"net/http"
)
type fileWithProgress struct {
http.File
size int64
downloaded int64
lastReported int64
name string
client string
}
func (f *fileWithProgress) Read(p []byte) (n int, err error) {
n, err = f.File.Read(p)
f.downloaded += int64(n)
f.lastReported += int64(n)
if f.lastReported > 1_000_000 { // report every 1e6 bytes
println("client:", f.client, "file:", f.name, "downloaded:", f.downloaded*100/f.size, "%")
f.lastReported = 0
}
return n, err
}
func (f *fileWithProgress) Seek(offset int64, whence int) (int64, error) {
f.downloaded = 0 // reset content detection read if no content-type specified
return f.File.Seek(offset, whence)
}
func (f *fileWithProgress) Close() error {
println("client:", f.client, "file:", f.name, "done", f.downloaded, "of", f.size, "bytes")
return f.File.Close()
}
type dirWithProgress struct {
http.FileSystem
client string
}
func (d *dirWithProgress) Open(name string) (http.File, error) {
println("open:", name, "for the client:", d.client)
f, err := d.FileSystem.Open(name)
if err != nil {
return nil, err
}
st, err := f.Stat()
if err != nil {
return nil, err
}
return &fileWithProgress{File: f, size: st.Size(), name: st.Name(), client: d.client}, nil
}
func fileServer(fs http.FileSystem) http.Handler {
f := func(w http.ResponseWriter, r *http.Request) {
progressDir := dirWithProgress{FileSystem: fs, client: r.RemoteAddr}
http.FileServer(&progressDir).ServeHTTP(w, r)
}
return http.HandlerFunc(f)
}
func main() {
dir := http.Dir(".")
fs := fileServer(dir)
http.Handle("/", fs)
http.ListenAndServe("127.0.0.1:8080", nil)
}

How does middleware work in chi routing in Go and what does http.Handler argument refers to in middleware?

-- routes.go --
package main
import (
"hotelsystem/pkg/config"
"hotelsystem/pkg/handlers"
"net/http"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
)
func routes(app *config.AppConfig) http.Handler {
mux := chi.NewRouter()
mux.Use(middleware.Recoverer)
mux.Use(WriteToConsole)
mux.Get("/", handlers.Repo.Home)
mux.Get("/about", handlers.Repo.About)
return mux
}
-- middleware.go --
package main
import (
"fmt"
"net/http"
)
func WriteToConsole(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Println("Hit the page")
next.ServeHTTP(w, r)
})
}
-- main.go --
package main
import (
"hotelsystem/pkg/config"
"hotelsystem/pkg/handlers"
"hotelsystem/pkg/render"
"log"
"net/http"
)
const portNumber = ":3000"
func main() {
var app config.AppConfig
tc, err := render.CreateTemplateCache()
if err != nil {
log.Fatal("Can't create templatecache", err)
}
app.TemplateCache = tc
app.UseCache = false
repo := handlers.NewRepo(&app)
handlers.NewHandlers(repo)
render.NewTemplate(&app)
// http.HandleFunc("/", handlers.Repo.Home)
// http.HandleFunc("/about", handlers.Repo.About)
// http.ListenAndServe(portNumber, nil)
srv := &http.Server{
Addr: portNumber,
Handler: routes(&app),
}
err = srv.ListenAndServe()
if err != nil {
log.Fatal(err)
}
}
I am having a hard time understanding the middleware.
I am using chi for routing.
What I didn't understand is what does that (next http.Handler) argument in the WriteToConsole refers to?
Does it refer to our mux router?
Also when I comment down the line next.ServeHTTP of function writetoconsole the html is not rendered or anything? can someone explain me what does that next http.Handler refers to and what next.serveHTTP does?
next is the next handler in the "handler chain".
When you do:
mux.Use(middleware.Recoverer)
mux.Use(WriteToConsole)
mux.Get("/", handlers.Repo.Home)
mux.Get("/about", handlers.Repo.About)
You are essentially registering two "handler chains":
mux.Get("/", middleware.Recoverer(WriteToConsole(handlers.Repo.Home)))
mux.Get("/about", middleware.Recoverer(WriteToConsole(handlers.Repo.About)))
Each handler returned by the middleware function has to invoke the next handler given to it, i.e. do next.ServeHTTP(w, r), if it doesn't invoke next then the chain is broken and the rest of the handlers in that chain will be ignored.
A simplified code example may illustrate the chaining better:
type handler func()
// your handler
func f() { fmt.Println("f") }
// one middleware
func g(next handler) handler {
return func() {
fmt.Print("g.")
next()
}
}
// another middleware
func h(next handler) handler {
return func() {
fmt.Print("h.")
next()
}
}
With the above you can then do:
func main() {
h1 := h(g(f))
h1()
h2 := g(h(f))
h2()
// And you can chain as many of these as you like
// and in any order you like.
h3 := h(g(h(h(h(g(g(h(f))))))))
h3()
}
https://play.golang.org/p/4NXquYsaljr

Get Request in Golang

this is a textbook example I try to put in use.
I get "BAD" as a result, it means that resp is nil, though I don't know how to fix it.
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
)
func main() {
resp, _ := http.Get("http://example.com/")
if resp != nil {
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
resp.Body.Close()
} else {
fmt.Println("BAD")
}
}
I would recommend to check your Internet settings first, as I cannot reproduce the problem.
Also, error handling in Go is crucial, so change your code to the one below and see if you get any error when making the request.
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
)
func main() {
resp, err := http.Get("http://example.com/")
if err != nil {
log.Fatalln(err)
}
if resp != nil {
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatalln(err)
}
fmt.Println(string(body))
resp.Body.Close()
} else {
fmt.Println("BAD")
}
}

Golang Error: Undefined: http.NewSingleHostReverseProxy

I tried building a simple program using Golang, here it is:
package main
import (
"net/http"
"net/http/httputil"
"log"
)
func main(){
proxy := http.NewSingleHostReverseProxy( &http.URL{Scheme:"http",Host:"www.google.com",Path:"/"})
err := http.ListenAndServe(":8080", proxy)
if err != nil {
log.Fatal("ListenAndServe: ", err.String())
}
}
Build:
go build myprogram.go
Output:
command-line-arguments
./myprogram.go:5: imported and not used: "net/http/httputil"
./myprogram.go:11: undefined: http.NewSingleHostReverseProxy
./myprogram.go:11: undefined: http.URL
./myprogram.go:15: err.String undefined (type error has no field or method String)
I noticed that http.NewSingleHostReverseProxy is in the "net/http/httputil" package, so why did I see such errors?
Maybe I need a specific command to build it correctly?
EDIT
Afterwords, here is the new working code:
package main
import (
"net/http"
"net/http/httputil"
"net/url"
"log"
)
func main(){
proxy := httputil.NewSingleHostReverseProxy( &url.URL{Scheme:"http",Host:"www.google.com",Path:"/"})
err := http.ListenAndServe(":8080", proxy)
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
I added
"net/url"
And replaced http.NewSingleHostReverseProxy with httputil.NewSingleHostReverseProxy, also
http.URL with url.URL.
This is the working code:
package main
import (
"net/http"
"net/http/httputil"
"net/url"
"log"
)
func main(){
proxy := httputil.NewSingleHostReverseProxy( &url.URL{Scheme:"http",Host:"www.google.com",Path:"/"})
err := http.ListenAndServe(":8080", proxy)
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
Thanks to raina77ow for help.

How to write `cat` in Go using pipes

I have an implementation of the Unix tool cat below. It reads a number of bytes from os.Stdin into a buffer, then writes those bytes out to os.Stdout. Is there a way I can skip the buffer and just pipe Stdin directly to Stdout?
package main
import "os"
import "io"
func main() {
buf := make([]byte, 1024)
var n int
var err error
for err != io.EOF {
n, err = os.Stdin.Read(buf)
if n > 0 {
os.Stdout.Write(buf[0:n])
}
}
}
You can use io.Copy() (Documentation here)
Example:
package main
import (
"os"
"io"
"log"
)
func main() {
if _, err := io.Copy(os.Stdout, os.Stdin); err != nil {
log.Fatal(err)
}
}
For example,
package main
import (
"io"
"os"
)
func main() {
io.Copy(os.Stdout, os.Stdin)
}

Resources