1
1
package tests
2
2
3
3
import (
4
+ "bytes"
5
+ "crypto/hmac"
6
+ "crypto/sha256"
7
+ "crypto/tls"
8
+ "encoding/base64"
4
9
"encoding/json"
10
+ "net/http"
11
+ "net/http/httptest"
5
12
"testing"
6
13
7
14
"github.com/line/line-bot-sdk-go/v8/linebot/webhook"
@@ -26,3 +33,95 @@ func TestStickerMessage(t *testing.T) {
26
33
t .Fatalf ("Failed to cast to UnknownEvent: %v" , cb .Events [0 ])
27
34
}
28
35
}
36
+
37
+ func generateSignature (secret string , body []byte ) string {
38
+ mac := hmac .New (sha256 .New , []byte (secret ))
39
+ mac .Write (body )
40
+ return base64 .StdEncoding .EncodeToString (mac .Sum (nil ))
41
+ }
42
+
43
+ func makeRequest (t * testing.T , url string , body []byte , signature string ) * http.Request {
44
+ req , err := http .NewRequest ("POST" , url , bytes .NewReader (body ))
45
+ if err != nil {
46
+ t .Fatalf ("failed to create request: %v" , err )
47
+ }
48
+ req .Header .Set ("X-Line-Signature" , signature )
49
+ return req
50
+ }
51
+
52
+ func TestWebhookParseRequestWithOption (t * testing.T ) {
53
+ const channelSecret = "testsecret"
54
+ body := []byte (`{"destination":"U0123456789abcdef","events":[]}` )
55
+
56
+ tests := []struct {
57
+ name string
58
+ skipValidation bool
59
+ useValidSig bool
60
+ expectedCode int
61
+ }{
62
+ {
63
+ name : "valid signature, no skip" ,
64
+ skipValidation : false ,
65
+ useValidSig : true ,
66
+ expectedCode : http .StatusOK ,
67
+ },
68
+ {
69
+ name : "invalid signature, no skip" ,
70
+ skipValidation : false ,
71
+ useValidSig : false ,
72
+ expectedCode : http .StatusBadRequest ,
73
+ },
74
+ {
75
+ name : "invalid signature, but skip = true" ,
76
+ skipValidation : true ,
77
+ useValidSig : false ,
78
+ expectedCode : http .StatusOK ,
79
+ },
80
+ }
81
+
82
+ for _ , tt := range tests {
83
+ t .Run (tt .name , func (t * testing.T ) {
84
+ handler := http .HandlerFunc (func (w http.ResponseWriter , req * http.Request ) {
85
+ opt := & webhook.ParseOption {
86
+ SkipSignatureValidation : func () bool { return tt .skipValidation },
87
+ }
88
+ cb , err := webhook .ParseRequestWithOption (channelSecret , req , opt )
89
+ if err != nil {
90
+ if err == webhook .ErrInvalidSignature {
91
+ w .WriteHeader (http .StatusBadRequest )
92
+ return
93
+ }
94
+ t .Errorf ("unexpected error: %v" , err )
95
+ w .WriteHeader (http .StatusInternalServerError )
96
+ return
97
+ }
98
+ if cb .Destination != "U0123456789abcdef" {
99
+ t .Errorf ("destination = %s; want %s" , cb .Destination , "U0123456789abcdef" )
100
+ }
101
+ w .WriteHeader (http .StatusOK )
102
+ })
103
+
104
+ server := httptest .NewTLSServer (handler )
105
+ defer server .Close ()
106
+
107
+ signature := "invalid"
108
+ if tt .useValidSig {
109
+ signature = generateSignature (channelSecret , body )
110
+ }
111
+ req := makeRequest (t , server .URL , body , signature )
112
+
113
+ client := & http.Client {
114
+ Transport : & http.Transport {
115
+ TLSClientConfig : & tls.Config {InsecureSkipVerify : true },
116
+ },
117
+ }
118
+ res , err := client .Do (req )
119
+ if err != nil {
120
+ t .Fatalf ("request failed: %v" , err )
121
+ }
122
+ if res .StatusCode != tt .expectedCode {
123
+ t .Errorf ("StatusCode = %d; want %d" , res .StatusCode , tt .expectedCode )
124
+ }
125
+ })
126
+ }
127
+ }
0 commit comments