수색…


비고

http.ServeMux 는 HTTP 요청에 대한 핸들러를 호출하는 멀티플렉서를 제공합니다.

표준 라이브러리 멀티플렉서의 대안은 다음과 같습니다.

사용자 정의 서버 및 멀티플렉서가있는 HTTP Hello World

package main

import (
    "log"
    "net/http"
)

func main() {

    // Create a mux for routing incoming requests
    m := http.NewServeMux()

    // All URLs will be handled by this function
    m.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte("Hello, world!"))
    })

    // Create a server listening on port 8000
    s := &http.Server{
        Addr:    ":8000",
        Handler: m,
    }

    // Continue to process new requests until an error occurs
    log.Fatal(s.ListenAndServe())
}

Ctrl + C 를 눌러 프로세스를 중지하십시오.

안녕하세요 세계

golang에 웹 서버를 작성하는 일반적인 방법은 표준 라이브러리 net/http 모듈을 사용하는 것입니다.

여기에 대한 자습서도 있습니다 .

다음 코드는 또한 그것을 사용합니다. 다음은 가능한 가장 간단한 HTTP 서버 구현입니다. HTTP 요청에 "Hello World" 를 응답합니다.

작업 영역의 server.go 파일에 다음 코드를 저장하십시오.

package main

import (
    "log"
    "net/http"
)

func main() {
    // All URLs will be handled by this function
    // http.HandleFunc uses the DefaultServeMux
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte("Hello, world!"))
    })

    // Continue to process new requests until an error occurs
    log.Fatal(http.ListenAndServe(":8080", nil))
}

다음을 사용하여 서버를 실행할 수 있습니다.

$ go run server.go

또는 컴파일하고 실행할 수 있습니다.

$ go build server.go
$ ./server

서버는 지정된 포트 ( :8080 )를 청취합니다. 모든 HTTP 클라이언트로 테스트 할 수 있습니다. 다음은 cURL 사용한 예입니다.

curl -i http://localhost:8080/
HTTP/1.1 200 OK
Date: Wed, 20 Jul 2016 18:04:46 GMT
Content-Length: 13
Content-Type: text/plain; charset=utf-8

Hello, world!

Ctrl + C 를 눌러 프로세스를 중지하십시오.

핸들러 함수 사용하기

HandleFunc 는 주어진 패턴에 대한 핸들러 함수를 서버 mux (라우터)에 등록합니다.

기본 Hello World 예제에서 보았 듯이 익명 함수를 정의하여 전달할 수 있습니다.

http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintln(w, "Hello, world!")
}

HandlerFunc 유형을 전달할 수도 있습니다. 즉, 다음 시그니처를 존중하는 함수를 전달할 수 있습니다.

func FunctionName(w http.ResponseWriter, req *http.Request)

이전에 정의한 HandlerFunc 대한 참조를 전달하는 이전 예제를 다시 작성할 수 있습니다. 전체 예제는 다음과 같습니다.

package main

import (
    "fmt"
    "net/http"
)

// A HandlerFunc function
// Notice the signature of the function
func RootHandler(w http.ResponseWriter, req *http.Request) {
    fmt.Fprintln(w, "Hello, world!")
}

func main() {
    // Here we pass the reference to the `RootHandler` handler function
    http.HandleFunc("/", RootHandler)
    panic(http.ListenAndServe(":8080", nil))
}

물론 여러 경로에 대해 여러 함수 핸들러를 정의 할 수 있습니다.

package main

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

func FooHandler(w http.ResponseWriter, req *http.Request) {
    fmt.Fprintln(w, "Hello from foo!")
}

func BarHandler(w http.ResponseWriter, req *http.Request) {
    fmt.Fprintln(w, "Hello from bar!")
}

func main() {
    http.HandleFunc("/foo", FooHandler)
    http.HandleFunc("/bar", BarHandler)

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

다음은 cURL 사용한 결과입니다.

➜  ~ curl -i localhost:8080/foo
HTTP/1.1 200 OK
Date: Wed, 20 Jul 2016 18:23:08 GMT
Content-Length: 16
Content-Type: text/plain; charset=utf-8

Hello from foo!

➜  ~ curl -i localhost:8080/bar
HTTP/1.1 200 OK
Date: Wed, 20 Jul 2016 18:23:10 GMT
Content-Length: 16
Content-Type: text/plain; charset=utf-8

Hello from bar!

➜  ~ curl -i localhost:8080/
HTTP/1.1 404 Not Found
Content-Type: text/plain; charset=utf-8
X-Content-Type-Options: nosniff
Date: Wed, 20 Jul 2016 18:23:13 GMT
Content-Length: 19

404 page not found

HTTPS 서버 만들기

인증서 생성

HTTPS 서버를 실행하려면 인증서가 필요합니다. openssl 하여 자체 서명 된 인증서를 생성하는 작업은 다음 명령을 실행하여 수행됩니다.

openssl req -x509 -newkey rsa:4096 -sha256 -nodes -keyout key.pem -out cert.pem -subj "/CN=example.com" -days 3650`

매개 변수는 다음과 같습니다.

  • req 인증서 요청 도구 사용
  • x509 자체 서명 된 인증서를 만듭니다.
  • newkey rsa:4096 4096 비트 키 길이의 RSA 알고리즘을 사용하여 새 키와 인증서를 만듭니다.
  • sha256 주요 브라우저가 안전한 것으로 간주하는 SHA256 해싱 알고리즘을 강제 실행합니다 (2017 년)
  • nodes 개인 키에 대한 암호 보호를 비활성화합니다. 이 매개 변수가 없으면 서버는 시작할 때마다 암호를 묻습니다.
  • keyout 파일에 키를 쓸 위치를 지정합니다.
  • out 인증서를 쓸 파일의 이름을 지정합니다.
  • subj 이 인증서가 유효한 도메인 이름을 정의합니다.
  • days Fow는이 인증서를 얼마나 유효해야합니까? 3650 은 대략입니다. 10 년.

참고 : 내부 프로젝트, 디버깅, 테스트 등을 위해 자체 서명 된 인증서를 사용할 수 있습니다. 모든 브라우저는이 인증서가 안전하지 않다고 언급 할 것입니다. 이를 피하기 위해 인증서는 인증 기관에서 서명해야합니다. 대부분 무료로 사용할 수 없습니다. 한 가지 예외는 "암호화하자"운동입니다 : https://letsencrypt.org

필요한 Go 코드

다음 코드를 사용하여 서버에 대한 TLS 구성을 처리 할 수 ​​있습니다. cert.pemkey.pem 은 위의 명령으로 생성 된 SSL 인증서 및 키입니다.

package main

import (
    "log"
    "net/http"
)

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte("Hello, world!"))
    })

    log.Fatal(http.ListenAndServeTLS(":443","cert.pem","key.pem", nil))
}

템플릿을 사용하여 HTTP 요청에 응답하기

Go의 템플리트를 사용하여 http.ResponseWriter 응답을 작성할 수 있습니다. 이것은 동적 인 페이지를 만들고자 할 때 유용한 툴로 입증됩니다.

Go에서 템플릿이 작동하는 방법을 보려면 Go Templates Documentation 페이지를 방문하십시오.

html/template 을 사용하여 HTTP 요청에 응답하는 간단한 예제를 계속 사용하십시오.

package main

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

func main(){
    http.HandleFunc("/",WelcomeHandler)
    http.ListenAndServe(":8080",nil)
}

type User struct{
    Name string
    nationality string //unexported field.
}

func check(err error){
    if err != nil{
        log.Fatal(err)
    }
}

func WelcomeHandler(w http.ResponseWriter, r *http.Request){
    if r.Method == "GET"{
        t,err := template.ParseFiles("welcomeform.html")
        check(err)
        t.Execute(w,nil)
    }else{
        r.ParseForm()
        myUser := User{}
        myUser.Name = r.Form.Get("entered_name")
        myUser.nationality = r.Form.Get("entered_nationality")
        t, err := template.ParseFiles("welcomeresponse.html")
        check(err)
        t.Execute(w,myUser)
    }
}

어디서,

  1. welcomeform.html 은 다음과 같습니다 :
<head>
    <title> Help us greet you </title>
</head>
<body>
    <form method="POST" action="/">
        Enter Name: <input type="text" name="entered_name">
        Enter Nationality: <input type="text" name="entered_nationality">
        <input type="submit" value="Greet me!">
    </form>
</body>
  1. welcomeresponse.html 은 다음과 같습니다.
<head>
    <title> Greetings, {{.Name}} </title>
</head>
<body>
    Greetings, {{.Name}}.<br>
    We know you are a {{.nationality}}!
</body>

노트 :

  1. .html 파일이 올바른 디렉토리에 있는지 확인하십시오.

  2. 서버를 시작한 후 http://localhost:8080/ 을 방문 할 수 있습니다.

  3. 이 양식을 제출 한 후 볼 수 있듯이 예상대로 구조체의 안 export 국적 필드는 템플릿 패키지 구문 분석 할 수 없습니다.

ServeMux를 사용하여 콘텐츠 제공

간단한 정적 파일 서버는 다음과 같습니다.

package main

import (
    "net/http"
)

func main() {
    muxer := http.NewServeMux()
    fileServerCss := http.FileServer(http.Dir("src/css"))
    fileServerJs := http.FileServer(http.Dir("src/js"))
    fileServerHtml := http.FileServer(http.Dir("content"))
    muxer.Handle("/", fileServerHtml)
    muxer.Handle("/css", fileServerCss)
    muxer.Handle("/js", fileServerJs)
    http.ListenAndServe(":8080", muxer)
}

http 메서드 처리, 쿼리 문자열 액세스 및 본문 요청

다음은 API 개발과 관련된 일반적인 작업의 간단한 예입니다. 요청의 HTTP 메소드를 구별하고, 쿼리 문자열 값에 액세스하고 요청 본문에 액세스합니다.

자원

package main

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

type customHandler struct{}

// ServeHTTP implements the http.Handler interface in the net/http package
func (h customHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {

    // ParseForm will parse query string values and make r.Form available
    r.ParseForm()

    // r.Form is map of query string parameters
    // its' type is url.Values, which in turn is a map[string][]string
    queryMap := r.Form

    switch r.Method {
    case http.MethodGet:
        // Handle GET requests
        w.WriteHeader(http.StatusOK)
        w.Write([]byte(fmt.Sprintf("Query string values: %s", queryMap)))
        return
    case http.MethodPost:
        // Handle POST requests
        body, err := ioutil.ReadAll(r.Body)
        if err != nil {
            // Error occurred while parsing request body
            w.WriteHeader(http.StatusBadRequest)
            return
        }
        w.WriteHeader(http.StatusOK)
        w.Write([]byte(fmt.Sprintf("Query string values: %s\nBody posted: %s", queryMap, body)))
        return
    }

    // Other HTTP methods (eg PUT, PATCH, etc) are not handled by the above
    // so inform the client with appropriate status code
    w.WriteHeader(http.StatusMethodNotAllowed)
}

func main() {
    // All URLs will be handled by this function
    // http.Handle, similarly to http.HandleFunc
    // uses the DefaultServeMux
    http.Handle("/", customHandler{})

    // Continue to process new requests until an error occurs
    log.Fatal(http.ListenAndServe(":8080", nil))
}

견본 컬 출력 :

$ curl -i 'localhost:8080?city=Seattle&state=WA' -H 'Content-Type: text/plain' -X GET
HTTP/1.1 200 OK
Date: Fri, 02 Sep 2016 16:36:24 GMT
Content-Length: 51
Content-Type: text/plain; charset=utf-8

Query string values: map[city:[Seattle] state:[WA]]%

$ curl -i 'localhost:8080?city=Seattle&state=WA' -H 'Content-Type: text/plain' -X POST -d "some post data"
HTTP/1.1 200 OK
Date: Fri, 02 Sep 2016 16:36:35 GMT
Content-Length: 79
Content-Type: text/plain; charset=utf-8

Query string values: map[city:[Seattle] state:[WA]]
Body posted: some post data%

$ curl -i 'localhost:8080?city=Seattle&state=WA' -H 'Content-Type: text/plain' -X PUT
HTTP/1.1 405 Method Not Allowed
Date: Fri, 02 Sep 2016 16:36:41 GMT
Content-Length: 0
Content-Type: text/plain; charset=utf-8


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow