gitee.com/openeuler/go-gitee@v0.0.0-20220530104019-3af895bc380c/gitee/messages.go (about)

     1  package gitee
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"fmt"
     7  	"io/ioutil"
     8  	"net/http"
     9  	"net/url"
    10  )
    11  
    12  /*
    13  Header Example:
    14  
    15  Request URL: http://gitee.com/webhook
    16  Request Method: POST
    17  Content-Type: application/json
    18  User-Agent: git-oschina-hook
    19  X-Gitee-Token: ******
    20  X-Gitee-Ping: false
    21  X-Gitee-Event: Merge Request Hook
    22  X-Git-Oschina-Event: Merge Request Hook
    23  
    24  */
    25  const (
    26  	// eventTypeHeader is the Gitee header key used to pass the event type.
    27  	eventTypeHeader = "X-Gitee-Event"
    28  	// tokenTypeHeader is the Gitee header key used to pass the webhook secret.
    29  	tokenTypeHeader = "X-Gitee-Token"
    30  )
    31  
    32  var (
    33  	// eventTypeMapping maps webhooks types
    34  	eventTypeMapping = map[string]string{
    35  		"Note Hook":          "NoteEvent",
    36  		"Push Hook":          "PushEvent",
    37  		"Issue Hook":         "IssueEvent",
    38  		"Merge Request Hook": "PullRequestEvent",
    39  		"Tag Push Hook":      "TagPushEvent",
    40  	}
    41  )
    42  
    43  // ValidatePayload validates an incoming Gitee Webhook event request
    44  func ValidatePayload(r *http.Request, secretKey []byte) (payload []byte, err error) {
    45  	var body []byte
    46  
    47  	switch ct := r.Header.Get("Content-Type"); ct {
    48  	case "application/json":
    49  		var err error
    50  		if body, err = ioutil.ReadAll(r.Body); err != nil {
    51  			return nil, err
    52  		}
    53  		payload = body
    54  	case "application/x-www-form-urlencoded":
    55  		const payloadFormParam = "payload"
    56  		var err error
    57  		if body, err = ioutil.ReadAll(r.Body); err != nil {
    58  			return nil, err
    59  		}
    60  		form, err := url.ParseQuery(string(body))
    61  		if err != nil {
    62  			return nil, err
    63  		}
    64  		payload = []byte(form.Get(payloadFormParam))
    65  	default:
    66  		return nil, fmt.Errorf("webhook request has unsupported Content-Type %q", ct)
    67  	}
    68  
    69  	token := r.Header.Get(tokenTypeHeader)
    70  	if token != string(secretKey) {
    71  		return nil, errors.New("payload token check failed")
    72  	}
    73  	return payload, nil
    74  }
    75  
    76  // WebHookType returns the event type of webhook request r.
    77  func WebHookType(r *http.Request) string {
    78  	return r.Header.Get(eventTypeHeader)
    79  }
    80  
    81  // ParseWebHook parses the event payload.
    82  func ParseWebHook(messageType string, payload []byte) (interface{}, error) {
    83  	eventType, ok := eventTypeMapping[messageType]
    84  	if !ok {
    85  		return nil, fmt.Errorf("unknown X-Gitee-Event in message: %v", messageType)
    86  	}
    87  	hookEvent := HookEvent{
    88  		Type:       &eventType,
    89  		RawPayload: (*json.RawMessage)(&payload),
    90  	}
    91  	return hookEvent.ParsePayload()
    92  }