Переглянути джерело

move server code to seperate file for unit testing

master
Patrick Peng Sun 8 роки тому
джерело
коміт
51ee339e77
3 змінених файлів з 163 додано та 115 видалено
  1. +0
    -115
      main.go
  2. +121
    -0
      server.go
  3. +42
    -0
      server_test.go

+ 0
- 115
main.go Переглянути файл

@@ -1,15 +1,8 @@
package main

import (
"crypto/sha1"
"fmt"
"io/ioutil"
"log"
"net/http"
"net/http/httputil"
"net/url"
"sort"
"strings"
)

func main() {
@@ -26,111 +19,3 @@ func main() {
//CreateDefaultMenu()
http.ListenAndServe(":65500", nil)
}

//apiV1Main version 1 main entry for all wechat callbacks
//
func apiV1Main(w http.ResponseWriter, r *http.Request) {
logRequestDebug(httputil.DumpRequest(r, true))

switch r.Method {
case "POST":
answerWechatPost(w, r)
case "GET":
answerInitialAuth(w, r)
default:
log.Fatalln(fmt.Sprintf("Unhandled HTTP %s", r.Method))
fmt.Fprintf(w, "Protocol Error: Expect GET or POST only")
}
}

//
//answerInitialAuth, when wechat first verify our URL for API hooks
//
func answerInitialAuth(w http.ResponseWriter, r *http.Request) {
rq := r.URL.RawQuery
m, _ := url.ParseQuery(rq)

echostr, eok := m["echostr"]
if checkSignature(r) && eok {
fmt.Fprintf(w, echostr[0])
} else {
fmt.Fprintf(w, "wtf is wrong with the Internet")
}
}

//answerWechatPost distribute PostRequest according to xml body info
//
func answerWechatPost(w http.ResponseWriter, r *http.Request) {
body, _ := ioutil.ReadAll(r.Body)
fmt.Printf("get body: %s", string(body))
s := ReadEncryptedMsg(string(body))
//fmt.Printf("to decrypt %s", s.Encrypt)
d := Decode(s.Encrypt)
fmt.Printf("decrypt as: %s", d)
h := ReadCommonHeader(d)
reply, _ := BuildTextMsg(h.MsgType, h.FromUserName)
fmt.Fprint(w, reply)
return
}

//
func checkSignature(r *http.Request) bool {
rq := r.URL.RawQuery
m, _ := url.ParseQuery(rq)

signature, sok := m["signature"]
timestamp, tok := m["timestamp"]
nonce, nok := m["nonce"]
token := APIConfig.Token
if sok && tok && nok {
//sort token, timestamp, nonce and join them
strs := []string{token, timestamp[0], nonce[0]}
sort.Strings(strs)
s := strings.Join(strs, "")

//calculate sha1
h := sha1.New()
h.Write([]byte(s))
calculated := fmt.Sprintf("%x", h.Sum(nil))
return signature[0] == calculated
}
return false
}

func checkSignature1() bool {
s1 := "e39de9f2e28079c01ebb4b803dfc3442b819545c"
t1 := "1492970761"
n1 := "1850971833"
token := APIConfig.Token

strs := []string{token, t1, n1}
sort.Strings(strs)
s := strings.Join(strs, "")

h := sha1.New()
h.Write([]byte(s))
us := fmt.Sprintf("%x", h.Sum(nil))
return s1 == us
}

//webrootHandler sending contents to client when request "/"
// essentially to prove the webserver is still alive
// echo query string to the client
func webrootHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
rq := r.URL.RawQuery
m, _ := url.ParseQuery(rq)
for index, element := range m {
fmt.Fprintf(w, "\r\n%s => %s", index, element)
}
logRequestDebug(httputil.DumpRequest(r, true))

}

func logRequestDebug(data []byte, err error) {
if err == nil {
fmt.Printf("%s\n\n", data)
} else {
log.Fatalf("%s\n\n", err)
}
}

+ 121
- 0
server.go Переглянути файл

@@ -0,0 +1,121 @@
package main

import (
"crypto/sha1"
"fmt"
"io/ioutil"
"log"
"net/http"
"net/http/httputil"
"net/url"
"sort"
"strings"
)

//apiV1Main version 1 main entry for all wechat callbacks
//
func apiV1Main(w http.ResponseWriter, r *http.Request) {
logRequestDebug(httputil.DumpRequest(r, true))

switch r.Method {
case "POST":
answerWechatPost(w, r)
case "GET":
answerInitialAuth(w, r)
default:
log.Fatalln(fmt.Sprintf("Unhandled HTTP %s", r.Method))
fmt.Fprintf(w, "Protocol Error: Expect GET or POST only")
}
}

//
//answerInitialAuth, when wechat first verify our URL for API hooks
//
func answerInitialAuth(w http.ResponseWriter, r *http.Request) {
rq := r.URL.RawQuery
m, _ := url.ParseQuery(rq)

echostr, eok := m["echostr"]
if checkSignature(r) && eok {
fmt.Fprintf(w, echostr[0])
} else {
fmt.Fprintf(w, "wtf is wrong with the Internet")
}
}

//answerWechatPost distribute PostRequest according to xml body info
//
func answerWechatPost(w http.ResponseWriter, r *http.Request) {
body, _ := ioutil.ReadAll(r.Body)
fmt.Printf("get body: %s", string(body))
s := ReadEncryptedMsg(string(body))
//fmt.Printf("to decrypt %s", s.Encrypt)
d := Decode(s.Encrypt)
fmt.Printf("decrypt as: %s", d)
h := ReadCommonHeader(d)
reply, _ := BuildTextMsg(h.MsgType, h.FromUserName)
fmt.Fprint(w, reply)
return
}

//
func checkSignature(r *http.Request) bool {
rq := r.URL.RawQuery
m, _ := url.ParseQuery(rq)

signature, sok := m["signature"]
timestamp, tok := m["timestamp"]
nonce, nok := m["nonce"]
token := APIConfig.Token
if sok && tok && nok {
//sort token, timestamp, nonce and join them
strs := []string{token, timestamp[0], nonce[0]}
sort.Strings(strs)
s := strings.Join(strs, "")

//calculate sha1
h := sha1.New()
h.Write([]byte(s))
calculated := fmt.Sprintf("%x", h.Sum(nil))
return signature[0] == calculated
}
return false
}

func checkSignature1() bool {
s1 := "e39de9f2e28079c01ebb4b803dfc3442b819545c"
t1 := "1492970761"
n1 := "1850971833"
token := APIConfig.Token

strs := []string{token, t1, n1}
sort.Strings(strs)
s := strings.Join(strs, "")

h := sha1.New()
h.Write([]byte(s))
us := fmt.Sprintf("%x", h.Sum(nil))
return s1 == us
}

//webrootHandler sending contents to client when request "/"
// essentially to prove the webserver is still alive
// echo query string to the client
func webrootHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
rq := r.URL.RawQuery
m, _ := url.ParseQuery(rq)
for index, element := range m {
fmt.Fprintf(w, "\r\n%s => %s", index, element)
}
logRequestDebug(httputil.DumpRequest(r, true))

}

func logRequestDebug(data []byte, err error) {
if err == nil {
fmt.Printf("%s\n\n", data)
} else {
log.Fatalf("%s\n\n", err)
}
}

+ 42
- 0
server_test.go Переглянути файл

@@ -0,0 +1,42 @@
package main

import (
"net/http"
"net/http/httptest"
"testing"
)

//when we setup wechate parameters,we chat will verify us
func TestInitialSetup(t *testing.T) {
SetupConfig()
}

func TestWebRootHandler(t *testing.T) {
// Create a request to pass to our handler. We don't have any query parameters for now, so we'll
// pass 'nil' as the third parameter.
req, err := http.NewRequest("GET", "/dummydir", nil)
if err != nil {
t.Fatal(err)
}

// We create a ResponseRecorder (which satisfies http.ResponseWriter) to record the response.
rr := httptest.NewRecorder()
handler := http.HandlerFunc(webrootHandler)

// Our handlers satisfy http.Handler, so we can call their ServeHTTP method
// directly and pass in our Request and ResponseRecorder.
handler.ServeHTTP(rr, req)

// Check the status code is what we expect.
if status := rr.Code; status != http.StatusOK {
t.Errorf("handler returned wrong status code: got %v want %v",
status, http.StatusOK)
}

// Check the response body is what we expect.
expected := `Hi there, I love dummydir!`
if rr.Body.String() != expected {
t.Errorf("handler returned unexpected body: got %v want %v",
rr.Body.String(), expected)
}
}

Завантаження…
Відмінити
Зберегти