Go Web Learning (2) — Внедрение промежуточного ПО (middleware)

Go

Вчера мы обсуждали, как язык Go использует стандартную библиотеку для реализации простой веб-версии HelloWorld, и у нас есть общее представление о процессе реализации серверных приложений на Go.Сегодня мы обсудим Middleware, реализующее http на языке Go.

Мы знаем, что большинство веб-приложений будут писать реализацию логики и функций в промежуточном программном обеспечении, чтобы сделать всю структуру более понятной.Промежуточное программное обеспечение в веб-приложениях грубо делится на два типа, а именно обработку ответа и обработку запроса (по моему скромному мнению, если есть любая ошибка Пожалуйста, поправьте меня), далее я реализую два способа написания промежуточного программного обеспечения в виде обработки запросов запросов.

Первый реализован в виде типа

В прошлом блоге мы обсудили основные части языка Go для реализации Интернета:

http.ListenAndServe(":8000", handler)

Функция streseandserve в пакете HTTP принимает два параметра, а именно адрес прослушивания и обработчик интерфейса обработки. Обработчик - это интерфейс. Нам нужно реализовать единственный метод в этом интерфейсе. ServHTTP может реализовывать вышеуказанные функции, поэтому вся логика и Процесс нашей обработки будет в этом обработке, давайте сначала посмотрим на простейшую реализацию обработчика.

package main

import (
	"net/http"
)

func myHandler(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("Hello World"))
}

func main() {
	http.ListenAndServe(":8000", http.HandlerFunc(myHandler))
}

Приведенный выше код, мы определяем MyHandler, он принимает HTTP.Responsewriter, * http.request Два параметра, затем снова отчетрийтеруйте пишущий Hello World, в основной функции, мы используем прямой способ прослушивания по прослушиванию. Сильный тип языка Go, ShistsAnceServe Вторым типом параметра является обработчик, поэтому мы хотим пройти MyHandler для прослушивания AdvantAndServe SERVEHTTP, этот метод должен быть реализован. Но на самом деле идет источник, который помог нам достичь этого метода.

// Handler that calls f.
type HandlerFunc func(ResponseWriter, *Request)

// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
	f(w, r)
}

Видно, что язык Go прямо определяет тип HandlerFunc для функций типа func(ResponseWriter, *Request), а также реализует метод ServeHTTP, но сам по себе этот метод не реализует никакой логики, и нам нужно реализовать его самим. Итак, мы реализуем метод myHandler, который будет выводить минимальный ответ HelloWorld. Затем мы можем использовать curl для проверки:

$ curl localhost:8000
Hello World

Как видите, мы запрашиваем локальный порт 8000 через curl и возвращаем нам HelloWorld. Это одна из самых простых реализаций Handler. Но наша цель реализовать middleware.Приведенными выше методами мы можем примерно понять, что myHandler нужно использовать как последний вызов, а middleware использовать перед ним.Тогда у нас есть общее В направлении, мы можем реализовать логику чтобы содержать этот myHandler, но он также должен реализовывать интерфейс Handler, потому что мы должны передать его методу ListenAndServe. Что ж, давайте кратко объясним роль этого промежуточного программного обеспечения.Он будет перехватывать все запросы, за исключением того, что хост этого запроса является хостом, который нам нужен.Конечно, этот хост имеет наше определение.

type SingleHost struct {
	handler     http.Handler
	allowedHost string
}

Таким образом, мы определяем структуру SingleHost, которая имеет два члена, один из них — Handler, который будет нашим выше myHandler, а другой — это пользователь, которому мы разрешаем запрашивать сервер, этот пользователь имеет уникальный хост, только когда он встречается с хостом. наши требования, запрос будет успешным, иначе будет возвращено 403.

Поскольку нам нужно создать экземпляр этого SingleHost и передать его методу ListenAndServe, он должен реализовать метод ServeHTTP, поэтому логика, которую мы используем для реализации промежуточного программного обеспечения, может быть непосредственно определена в ServeHTTP. То есть, если хост запрашивающего пользователя не разрешенHost, он всегда будет возвращать 403.

func (this *SingleHost) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if (r.Host == this.allowedHost) {
		this.handler.ServeHTTP(w, r)
	} else {
		w.WriteHeader(403)
	}
}

Что ж, мы можем ясно видеть, что только когда Host==allowedHost запроса, мы вызываем метод ServeHTTP обработчика, иначе возвращаем 403. Ниже приведен полный код:

package main

import (
	"net/http"
)

type SingleHost struct {
	handler     http.Handler
	allowedHost string
}

func (this *SingleHost) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if (r.Host == this.allowedHost) {
		this.handler.ServeHTTP(w, r)
	} else {
		w.WriteHeader(403)
	}
}

func myHandler(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("Hello World"))
}

func main() {
	single := &SingleHost{
		handler:http.HandlerFunc(myHandler),
		allowedHost:"refuse.com",
	}
	http.ListenAndServe(":8000", single)
}

Затем мы используем curl для запроса локального порта 8000,

$ curl --head localhost:8000
HTTP/1.1 403 Forbidden
Date: Sun, 21 Jan 2018 08:32:47 GMT
Content-Type: text/plain; charset=utf-8

Мы видим, что нам разрешен доступ к хосту только для логики reject.com, реализованной в промежуточном программном обеспечении, потому что завиток хоста является локальным хостом, поэтому мы возвращаем его непосредственно на сервер 403. Далее мы меняем то, что разрешеноHost

allowedHost:"localhost:8000",

Мы изменили allowHost на localhost:8000, а затем протестировали с помощью curl.

$ curl localhost:8000
Hello World

Вы можете видеть, что curl прошел промежуточное ПО и напрямую получил HelloWorld, возвращенный myHandler.

Второй реализован в виде функции

Ну, выше мы реализовали промежуточное ПО на основе типов.Люди, которые могут быть знакомы с Node.js, привыкли реализовывать промежуточное ПО в виде функций. Прежде всего, поскольку мы реализуем промежуточное ПО как функцию, эта функция возвращает Handler, который принимает два параметра: один — это myHandler, который мы определили, а другой — allowHost.

func SingleHost(handler http.Handler, allowedHost string) http.Handler {
	fn := func(w http.ResponseWriter, r *http.Request) {
		if r.Host == allowedHost {
			handler.ServeHTTP(w, r)
		} else {
			w.WriteHeader(403)
		}
	}
	return http.HandlerFunc(fn)
}

Видно, что мы определяем анонимную функцию fn внутри функции.Эта анонимная функция является обработчиком, который мы хотим вернуть.Если хост запрашивающего пользователя удовлетворяет разрешенному хосту, функция, которая вызывает myHandler, может быть возвращена, в противном случае она вернет операцию напрямую. 403 функция. Весь код выглядит следующим образом:

package main

import "net/http"

func SingleHost(handler http.Handler, allowedHost string) http.Handler {
	fn := func(w http.ResponseWriter, r *http.Request) {
		if r.Host == allowedHost {
			handler.ServeHTTP(w, r)
		} else {
			w.WriteHeader(403)
		}
	}
	return http.HandlerFunc(fn)
}

func myHandler(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("Hello World"))
}

func main() {
	single := SingleHost(http.HandlerFunc(myHandler), "refuse.com")
	http.ListenAndServe(":8000", single)
}

Мы тестируем его с помощью curl

$ curl --head localhost:8000
HTTP/1.1 403 Forbidden
Date: Sun, 21 Jan 2018 08:45:39 GMT
Content-Type: text/plain; charset=utf-8

Видно, что из-за того, что мы не удовлетворяем crute.com, мы получим 403, давайте изменим тест reject.com на localhost: 8000.

$ curl localhost:8000
Hello World

Как и прежде мы получили правильный результат HelloWorld. Ну, ту же самую функцию выше мы реализовали в виде функций.Конечно, оба метода осуществимы.В основном это зависит от личных предпочтений.Если мне нравится функциональное программирование, я все же предпочитаю второе (смеется). Вот и все на сегодня, я желаю Наггетс все лучше и лучше! ! !