Example #1
0
// DeliverHooks checks and delivers undelivered hooks.
// FIXME: maybe can use goroutine to shoot a number of them at same time?
func DeliverHooks() {
	if isShooting {
		return
	}
	isShooting = true
	defer func() { isShooting = false }()

	tasks := make([]*HookTask, 0, 10)
	timeout := time.Duration(setting.Webhook.DeliverTimeout) * time.Second
	x.Where("is_delivered=?", false).Iterate(new(HookTask),
		func(idx int, bean interface{}) error {
			t := bean.(*HookTask)
			req := httplib.Post(t.Url).SetTimeout(timeout, timeout).
				Header("X-Gogs-Delivery", t.Uuid).
				Header("X-Gogs-Event", string(t.EventType)).
				SetTLSClientConfig(&tls.Config{InsecureSkipVerify: setting.Webhook.SkipTLSVerify})

			switch t.ContentType {
			case JSON:
				req = req.Header("Content-Type", "application/json").Body(t.PayloadContent)
			case FORM:
				req.Param("payload", t.PayloadContent)
			}

			t.IsDelivered = true

			// FIXME: record response.
			switch t.Type {
			case GOGS:
				{
					if _, err := req.Response(); err != nil {
						log.Error(5, "Delivery: %v", err)
					} else {
						t.IsSucceed = true
					}
				}
			case SLACK:
				{
					if res, err := req.Response(); err != nil {
						log.Error(5, "Delivery: %v", err)
					} else {
						defer res.Body.Close()
						contents, err := ioutil.ReadAll(res.Body)
						if err != nil {
							log.Error(5, "%s", err)
						} else {
							if string(contents) != "ok" {
								log.Error(5, "slack failed with: %s", string(contents))
							} else {
								t.IsSucceed = true
							}
						}
					}
				}
			}

			tasks = append(tasks, t)

			if t.IsSucceed {
				log.Trace("Hook delivered(%s): %s", t.Uuid, t.PayloadContent)
			}
			return nil
		})

	// Update hook task status.
	for _, t := range tasks {
		if err := UpdateHookTask(t); err != nil {
			log.Error(4, "UpdateHookTask(%d): %v", t.Id, err)
		}
	}
}
Example #2
0
func (t *HookTask) deliver() {
	t.IsDelivered = true

	timeout := time.Duration(setting.Webhook.DeliverTimeout) * time.Second
	req := httplib.Post(t.URL).SetTimeout(timeout, timeout).
		Header("X-Gogs-Delivery", t.UUID).
		Header("X-Gogs-Event", string(t.EventType)).
		SetTLSClientConfig(&tls.Config{InsecureSkipVerify: setting.Webhook.SkipTLSVerify})

	switch t.ContentType {
	case JSON:
		req = req.Header("Content-Type", "application/json").Body(t.PayloadContent)
	case FORM:
		req.Param("payload", t.PayloadContent)
	}

	// Record delivery information.
	t.RequestInfo = &HookRequest{
		Headers: map[string]string{},
	}
	for k, vals := range req.Headers() {
		t.RequestInfo.Headers[k] = strings.Join(vals, ",")
	}

	t.ResponseInfo = &HookResponse{
		Headers: map[string]string{},
	}

	defer func() {
		t.Delivered = time.Now().UnixNano()
		if t.IsSucceed {
			log.Trace("Hook delivered: %s", t.UUID)
		} else {
			log.Trace("Hook delivery failed: %s", t.UUID)
		}

		// Update webhook last delivery status.
		w, err := GetWebhookByRepoID(t.RepoID, t.HookID)
		if err != nil {
			log.Error(5, "GetWebhookByID: %v", err)
			return
		}
		if t.IsSucceed {
			w.LastStatus = HOOK_STATUS_SUCCEED
		} else {
			w.LastStatus = HOOK_STATUS_FAILED
		}
		if err = UpdateWebhook(w); err != nil {
			log.Error(5, "UpdateWebhook: %v", err)
			return
		}
	}()

	resp, err := req.Response()
	if err != nil {
		t.ResponseInfo.Body = fmt.Sprintf("Delivery: %v", err)
		return
	}
	defer resp.Body.Close()

	// Status code is 20x can be seen as succeed.
	t.IsSucceed = resp.StatusCode/100 == 2
	t.ResponseInfo.Status = resp.StatusCode
	for k, vals := range resp.Header {
		t.ResponseInfo.Headers[k] = strings.Join(vals, ",")
	}

	p, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		t.ResponseInfo.Body = fmt.Sprintf("read body: %s", err)
		return
	}
	t.ResponseInfo.Body = string(p)
}