creating web server in golang

c

web server is server software, or hardware dedicated to running such software, that can satisfy World Wide Web client requests. A web server can, in general, contain one or more websites. A web server processes incoming network requests over HTTP and several other related protocols. The primary function of a web server is to store, process and deliver web pages to clients.[1] The communication between client and server takes place using the Hypertext Transfer Protocol (HTTP). Pages delivered are most frequently HTML documents, which may include imagesstyle sheets and scripts in addition to the text content.

Representational state transfer (REST) is a software architectural style that defines a set of constraints to be used for creating Web services. Web services that conform to the REST architectural style, called RESTful Web services, provide interoperability between computer systems on the Internet. RESTful Web services allow the requesting systems to access and manipulate textual representations of Web resources by using a uniform and predefined set of stateless operations. Other kinds of Web services, such as SOAP Web services, expose their own arbitrary sets of operations.[

(source: wikipedia)

Basically whenever we type “google.com” in the browser, the browser sends a HTTP request to the google server. And then the server responds with some data. This data can be of anything like text, json, xml etc

First run the below go command

go get -u github.com/gorilla/mux

We’re going to use a library named MUX. https://github.com/gorilla/mux

Basic web server

By the end of this article, we gonna build this web app

To create web server include "net/http"

use http.HandleFunc to listen for the incoming request

use http.ListenAndServe to actually start listening

Here’s a basic example:

package main

import (
	"fmt"
	"html"
	"log"
	"net/http"
)

func main() {

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
	})

	log.Fatal(http.ListenAndServe(":8080", nil))

}

Its not a problem for the above code, but still its good to separate those with functions.

package main

import (
	"fmt"
	"html"
	"log"
	"net/http"
)

func indexHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
}

func main() {

	http.HandleFunc("/", indexHandler)

	log.Fatal(http.ListenAndServe(":8080", nil))

}

Run the above program. Go to http://localhost:8080/ in your browser

You should see the above result.

Well, obviously as our project starts to get bigger, things will get complex if we only used the http module

So we’re gonna use mux

mux

  1. initialize mux router r := mux.NewRouter()
  2. use r.HandleFunc to handle routes
  3. start the server with mux http.ListenAndServe(":8000", r)
package main

import (
	"fmt"
	"log"
	"net/http"

	"github.com/gorilla/mux"
)

func getTodos(w http.ResponseWriter, r *http.Request) {
	fmt.Println("todos")
}

// Main function
func main() {
	// Init router
	r := mux.NewRouter()

	// Route handles & endpoints
	r.HandleFunc("/todos", getTodos).Methods("GET")

	// Start server
	log.Fatal(http.ListenAndServe(":8080", r))
}

And if you go to http://localhost:8080/todos

you’ll see the output as expected

But I want send some data not a simple print statement right?

Ok. So lets send some JSON

func getTodos(w http.ResponseWriter, r *http.Request) {
	fmt.Println("todos")
	json.NewEncoder(w).Encode("hi")
}

Now if you re-run the code, you should see this:

A dynamic endpoint

So far we’ve seen some basic endpoints but what about links like this /todo/1 or /todo/2

r.HandleFunc("/todo/{id}", getTodo).Methods("GET")

Now to get the id use mux.Vars(r). This will return all the params. To get the id param, use mux.Vars(r)["id"]

func getTodo(w http.ResponseWriter, r *http.Request) {
	params := mux.Vars(r) // Gets params

	id := params["id"]
	fmt.Println("todo item at", id)
	json.NewEncoder(w).Encode("item at " + id)
}

Now if you go to http://localhost:8080/todo/1

and for http://localhost:8080/todo/12

Here’s the complete code:

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"

	"github.com/gorilla/mux"
)

func getTodos(w http.ResponseWriter, r *http.Request) {
	fmt.Println("todos")
	json.NewEncoder(w).Encode("hi")
}

func getTodo(w http.ResponseWriter, r *http.Request) {
	params := mux.Vars(r) // Gets params

	id := params["id"]
	fmt.Println("todo item at", id)
	json.NewEncoder(w).Encode("item at " + id)
}

// Main function
func main() {
	// Init router
	r := mux.NewRouter()

	// Route handles & endpoints
	r.HandleFunc("/todos", getTodos).Methods("GET")
	r.HandleFunc("/todo/{id}", getTodo).Methods("GET")
	// Start server
	log.Fatal(http.ListenAndServe(":8080", r))
}

Ok thats all for api calls.

What about sending HTML pages?

templates

Well look at our first example

package main

import (
	"fmt"
	"html"
	"log"
	"net/http"
)

func main() {

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
	})

	log.Fatal(http.ListenAndServe(":8080", nil))

}

We can actually write HTML here!

package main

import (
	"fmt"
	"log"
	"net/http"
)

func main() {

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "<h1>This is html h1 tag</h1>")
		fmt.Fprintf(w, "<p>This is html p tag</p>")
	})

	log.Fatal(http.ListenAndServe(":8080", nil))

}

You can use any html tags here.

package main

import (
	"fmt"
	"log"
	"net/http"
)

func main() {

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "<h1>Kazuma quotes:</h1>")
		fmt.Fprintf(w, "<img src=\"https://i.ytimg.com/vi/NqLzs_RxRhU/maxresdefault.jpg\" \\>")
	})

	log.Fatal(http.ListenAndServe(":8080", nil))

}

Sure, this works. But it kinda makes your code messy. I mean combining html and go in a single file?

Lets separate it.

import html/template

and change the handler function

package main

import (
	"log"
	"net/http"
	"html/template"
)

func main() {

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		t, _ := template.ParseFiles("index.html")
		t.Execute(w, nil)
		
	})

	log.Fatal(http.ListenAndServe(":8080", nil))

}

And type this in your newly created index.html

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<meta http-equiv="X-UA-Compatible" content="ie=edge" />
		<title>Anime quotes</title>
	</head>
	<body>
		<h1>Kazuma quotes:</h1>
		<img src="https://i.ytimg.com/vi/NqLzs_RxRhU/maxresdefault.jpg" />
	</body>
</html>

Re-run the code. And it will still work

Happy coding!

About the author

vigneshwar

Add comment

Leave a Reply

By vigneshwar

Most common tags

%d bloggers like this: