質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
JWT(JSON Web Token)

JWT(JSON Web Token)とは、JSONをベースとしたアクセストークンの仕様。電子署名付きのURL safeなJSONのことを指します。電子署名が付いているため、改ざんをチェックできる点がメリットです。

Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

Webサーバー

Webサーバーとは、HTTPリクエストに応じて、クライアントに情報を提供するシステムです。

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

Q&A

解決済

2回答

1415閲覧

gorilla/muxで、リクエストを正しく処理できない

BraveDragon

総合スコア15

JWT(JSON Web Token)

JWT(JSON Web Token)とは、JSONをベースとしたアクセストークンの仕様。電子署名付きのURL safeなJSONのことを指します。電子署名が付いているため、改ざんをチェックできる点がメリットです。

Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

Webサーバー

Webサーバーとは、HTTPリクエストに応じて、クライアントに情報を提供するシステムです。

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

0グッド

0クリップ

投稿2021/05/02 09:27

前提・実現したいこと

現在、Goを利用してAPIサーバーを実装する練習をしています。ユーザー作成・ユーザー情報取得・ユーザー情報更新の処理を作成し、ユーザー認証とトークンのリフレッシュ、CORS対応をミドルウェアで実装しました。また、サブルーターの機能を利用して、ユーザー認証とトークンのリフレッシュのミドルウェアを必要とするルートと必要としないルートを分けました。
処理が正しく実行できるか、試しにPostmanを利用して/user/createにjsonリクエストを送ったのですが、Postmanのコンソール上で

POST https://localhost:8080/user/create Error: connect ECONNREFUSED 127.0.0.1:8080 Request Headers Content-Type: "application/json" User-Agent: "PostmanRuntime/7.28.0" Accept: "*/*" Postman-Token: "aab94c94-15a7-476d-841a-6afa1d91e124" Host: "localhost:8080" Accept-Encoding: "gzip, deflate, br" Connection: "keep-alive" Request Body { "name": "ABC", "mailAddress": "kefdd", "passWord": "dergrgf" }

というエラーが発生し、接続が中止されてしまいました。
どうすればこのエラーを解決して、正しく実行(例えば/user/createにリクエストを送ればユーザーが作成される)されるようになるでしょうか?

発生している問題・エラーメッセージ

  • 現在、Goを利用してAPIサーバーを実装する練習をしている
  • ユーザー作成・ユーザー情報取得・ユーザー情報更新の処理を作成し、ユーザー認証とトークンのリフレッシュ、CORS対応をミドルウェアで実装した
  • サブルーターの機能を利用して、ユーザー認証とトークンのリフレッシュのミドルウェアを必要とするルートと必要としないルートを分けた
  • 処理が正しく実行できるか、試しにPostmanを利用して/user/createにjsonリクエストを送ったところ、Postmanのコンソール上で以下のようなエラーが発生し、接続が中止されてしまった
POST https://localhost:8080/user/create Error: connect ECONNREFUSED 127.0.0.1:8080 Request Headers Content-Type: "application/json" User-Agent: "PostmanRuntime/7.28.0" Accept: "*/*" Postman-Token: "aab94c94-15a7-476d-841a-6afa1d91e124" Host: "localhost:8080" Accept-Encoding: "gzip, deflate, br" Connection: "keep-alive" Request Body { "name": "ABC", "mailAddress": "kefdd", "passWord": "dergrgf" }
  • このエラーを解決し、正しく実行(例えば/user/createにリクエストを送ればユーザーが作成される)されるようにしたい

該当のソースコード

main.goのソースコード

Go

1package main 2 3import ( 4 "log" 5 "net/http" 6 7 "Project/handler/userhandler" 8 "Project/middleware" 9 10 "github.com/gorilla/mux" 11) 12 13func main() { 14 15 router := mux.NewRouter() 16 router.Schemes("https") 17 //ユーザー認証をする処理用のルーター 18 authorizationRouteCreator := router.Host("https://localhost:8080").Subrouter() 19 authorizationRouteCreator.Headers("X-Requested-With", "XMLHttpRequest") 20 //ユーザー認証をしない処理用のルーター 21 otherRouteCreator := router.Host("https://localhost:8080").Subrouter() 22 23 //ユーザー認証とトークンのリフレッシュはミドルウェアで行う 24 authorizationRouteCreator.Use(middleware.AuthorizationMiddleware) 25 authorizationRouteCreator.Use(middleware.RefreshMiddleware) 26 //CORS対応もミドルウェアで行う 27 authorizationRouteCreator.Use(middleware.EnableCorsMiddleware) 28 29 //CORS対応もミドルウェアで行う 30 otherRouteCreator.Use(middleware.EnableCorsMiddleware) 31 32 //エンドポイントを用意 33 //ユーザー作成 34 otherRouteCreator.HandleFunc("/user/create", userhandler.UserCreate).Methods("POST") 35 36 //ユーザー情報取得 37 authorizationRouteCreator.HandleFunc("/user/get", userhandler.UserGet(userhandler.UserGetImpl)).Methods("GET") 38 39 //ユーザー情報更新 40 authorizationRouteCreator.HandleFunc("/user/update", userhandler.UserUpdate).Methods("PUT") 41 42 log.Fatal(http.ListenAndServe(":8080", router)) 43 44} 45 46※userhandler.UserCreateはユーザーの新規作成を行う関数。 47※userhandler.UserGetとuserhandler.UserGetImplはユーザー情報取得を行う関数。 48※userhandler.UserUpdateはユーザー情報更新を行う関数。

middleware.goのソースコード

Go

1package middleware 2 3import ( 4 "Project/controller/usercontroller" 5 "Project/handler/handlerutil" 6 "Project/handler/userhandler" 7 "net/http" 8 "time" 9) 10 11//AuthorizationMiddleware : ユーザー認証用のミドルウェア. 12func AuthorizationMiddleware(next http.Handler) http.Handler { 13 return http.HandlerFunc( 14 func(w http.ResponseWriter, r *http.Request) { 15 usercontroller.UserSignIn(w, r) 16 next.ServeHTTP(w, r) 17 }) 18} 19 20//RefreshMiddleware : トークンのリフレッシュ用のミドルウェア. 21func RefreshMiddleware(next http.Handler) http.Handler { 22 return http.HandlerFunc( 23 func(w http.ResponseWriter, r *http.Request) { 24 // トークンの検証(有効かどうか) 25 _, jsonToken, _, err := userhandler.CheckPasetoAuth(w, r) 26 if err != nil { 27 //トークンが無効ならエラーを返す 28 handlerutil.ErrorLoggingAndWriteHeader(w, err, http.StatusUnauthorized) 29 30 } 31 now := time.Now() 32 //トークンの有効期限がまだ切れていない時は何もせずにそのまま返す 33 if jsonToken.Expiration.After(now) { 34 w.WriteHeader(http.StatusOK) 35 36 } else { 37 //有効期限が切れていたらもう一度サインインしてトークンをリフレッシュ 38 usercontroller.UserSignIn(w, r) 39 w.WriteHeader(http.StatusOK) 40 41 } 42 next.ServeHTTP(w, r) 43 }) 44 45} 46 47//EnableCorsMiddleware : CORS対応用のミドルウェア. 48func EnableCorsMiddleware(next http.Handler) http.Handler { 49 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 50 w.Header().Set("Access-Control-Allow-Origin", "*") 51 w.Header().Add("Access-Control-Allow-Methods", "GET, POST, PUT, OPTIONS") 52 w.Header().Add("Access-Control-Allow-Headers", "*") 53 //プリフライトリクエストの場合の処理 54 if r.Method == "OPTIONS" { 55 w.WriteHeader(http.StatusOK) 56 return 57 } 58 next.ServeHTTP(w, r) 59 60 }) 61 62} 63 64※userhandler.CheckPasetoAuthはトークンの検証を行う関数。 65※usercontroller.UserSignInはユーザーのサインインを行う関数。

handlerutil.goのソースコード

Go

1package handlerutil 2 3import ( 4 "encoding/json" 5 "log" 6 "net/http" 7 "errors" 8) 9 10//ParseJsonBody : JSONボディから必要なデータを取得. 11func ParseJsonBody(r *http.Request, decordtarget interface{}) error { 12 err := json.NewDecoder(r.Body).Decode(&decordtarget) 13 if err != nil { 14 return errors.New("the json body is incorrect!") 15 } else { 16 return nil 17 } 18} 19 20//ErrorLoggingAndWriteHeader : errのnilチェック+Log吐き+httpステータスをw.WriteHeader()する. 21func ErrorLoggingAndWriteHeader(w http.ResponseWriter, err error, httpStatus int) { 22 log.Print(err.Error()) 23 w.WriteHeader(httpStatus) 24 25}

Postmanで送信したリクエストのjsonボディ

json

1{ 2 "name": "ABC", 3 "mailAddress": "kefdd", 4 "passWord": "dergrgf" 5}

Postmanで送信したリクエストの送信先:https://localhost:8080/user/create
Postmanで送信したリクエストのHTTPメソッド:POST
Postmanでの authorization methodのType:Bearer Token

試したこと

以下のサイトを参考にして、ソースコードを修正した上で、Postmanでjsonリクエストを送ってみましたが、依然として同様のエラーが発生しました。
https://qiita.com/gold-kou/items/99507d33b8f8ddd96e3a
https://gist.github.com/danesparza/eb3a63ab55a7cd33923e
https://mj-go.in/golang/crud-rest-api-with-gorilla-mux
https://qiita.com/unhurried/items/8bab83747130906885b7

補足情報(FW/ツールのバージョンなど)

Goのバージョン:1.16
gorilla/muxのバージョン:v1.8.0
Postmanのバージョン:v8.3.0

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

自己解決

main.goにおいて、

Go

1authorizationRouteCreator.Headers("X-Requested-With", "XMLHttpRequest") 2```  34```Go 5router.Schemes("http")

をコメントアウトし、

Go

1authorizationRouteCreator := router.Host("https://localhost:8080").Subrouter() 2otherRouteCreator := router.Host("https://localhost:8080").Subrouter()

をそれぞれ

Go

1authorizationRouteCreator := router.PathPrefix("").Subrouter() 2otherRouteCreator := router.PathPrefix("").Subrouter()

に書き換えた上で、

Go

1log.Fatal(http.ListenAndServe(":8080", router))

Go

1srv := &http.Server{ 2 Addr: ":8080", 3 Handler: router, 4 } 5log.Fatal(srv.ListenAndServe())

に書き換えたところ、正しくリクエストが処理できるようになりました。
どうやら、原因はヘッダーの設定をしていたからのようです。

投稿2021/05/09 02:25

BraveDragon

総合スコア15

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

クライアントがTLSセッション張ろうとしたがサーバーはTLSとしての応答を返さないから接続拒否してしまうようです。
サーバーがnotTLSサーバーなのが原因かと。

追記

ngrokというサービスを利用してみるのはどうでしょうか?

以下のようなコマンドを実行すると、

shell

1ngrok http localhost:8080

以下の転送ルートを用意してくれます(b412c1f182b7はその都度ランダムな文字列)。

https://b412c1f182b7.ngrok.io -> http://localhost:8080

行することでHTTPS(TLS)通信をHTTP(notTLS)にして手元のServerに中継してくれます。

つまり、
PostManで「https://b412c1f182b7.ngrok.io/user/create」にPOSTすると、
ngrokが「http://localhost:8080/user/create」にPOSTしてくれます。

投稿2021/05/02 12:11

編集2021/05/03 01:48
nobonobo

総合スコア3367

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

BraveDragon

2021/05/03 04:34

回答してくださり、誠にありがとうございます。 試してみます。
BraveDragon

2021/05/03 04:54

ngrokを試してみた結果についてご報告させていただきます。 ngrokをインストールし、「ngrok http localhost:8080」を実行してから、Postmanで「https://(自動生成されるランダム文字列).ngrok.io/user/create」にPOSTしてみたのですが、私が最初に述べていたエラーメッセージは表示されなかったものの、「ngrok http localhost:8080」を実行したコマンドプロンプトの画面上で「POST /user/create 404 Not Found 」というメッセージが表示されました。 どうやらルーティングがうまくできていないようなのですが、どうすれば正しくルーティングできるのでしょうか? よろしくお願いいたします。
nobonobo

2021/05/03 06:29 編集

ngrokは動作を保っていますか?(Postmanは別のコマンドプロンプトから実行しましょう) 上手く動いた場合、ngrokのコンソール画面に以下のような表示が出ると思います。 ``` ngrok by @inconshreveable (Ctrl+C to quit) Session Status online Session Expires 1 hour, 59 minutes Update update available (version 2.3.39, Ctrl-U to update) Version 2.3.35 Region United States (us) Web Interface http://127.0.0.1:4040 Forwarding http://e33cd21c4741.ngrok.io -> http://localhost:8080 Forwarding https://e33cd21c4741.ngrok.io -> http://localhost:8080 Connections ttl opn rt1 rt5 p50 p90 0 1 0.00 0.00 0.00 0.00 HTTP Requests ------------- POST /user/create 200 OK ``` あと、ソースコード上にある"https://localhost:8080"はすべて"https://ランダム文字列.ngrok.io"にすべきかと思います。 「router.Schemes("https")」は「router.Schemes("http")」である必要があるかと。
BraveDragon

2021/05/04 01:16

返信してくださり、誠にありがとうございます。 試してみます。
BraveDragon

2021/05/04 01:36 編集

試してみた結果について、報告させていただきます。 「router.Schemes("https")」は「router.Schemes("http")」に書き換えた上で、ソースコード上にある"https://localhost:8080"をすべて"https://ランダム文字列.ngrok.io"にしてから、「ngrok http localhost:8080」を実行してみたのですが、やはり「POST /user/create 404 Not Found 」というメッセージが表示されました。 ngrokのコンソール画面の表示は以下のようになっていました。 ngrok by @inconshreveable (Ctrl+C to quit) Session Status online Account BraveDragon (Plan: Free) Version 2.3.39 Region United States (us) Web Interface http://127.0.0.1:4040 Forwarding http://7e3a17d4835e.ngrok.io -> http://localhost:8080 Forwarding https://7e3a17d4835e.ngrok.io -> http://localhost:8080 Connections ttl opn rt1 rt5 p50 p90 0 1 0.00 0.00 0.00 0.00 HTTP Requests ------------- POST /user/create 404 Not Found POST /user/create 404 Not Found どうやら、「404 Not Found」の原因は他の部分にあるようです。 どうすれば「404 Not Found」のエラーが表示されずに、正しくリクエストが処理できるでしょうか? よろしくお願いいたします。
nobonobo

2021/05/04 13:54

router.Host("https://localhost:8080")にはホスト名を指定すべきで、ホスト名は「localhost:8080」になるような気がします。
BraveDragon

2021/05/05 01:47

返信誠にありがとうございます。 試してみます。
BraveDragon

2021/05/05 02:21

試してみた結果について、ご報告させていただきます。 Postmanにてhttp://localhost:8080/user/create へポストしてみましたが、やはり404が返ってきました。 router.Host("https://localhost:8080")をrouter.Host("localhost:8080")に書き換えてから同様のことを行いましたが、やはり404が返ってきました。 恐らく原因はルーターやサブルーターの作成方法、もしくはエンドポイントの作成方法にあると思うのですが、解決方法がわかりません。 どうすれば404を返さず、正しく処理を実行できるようになるでしょうか? よろしくお願いいたします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問