Example #1
0
func (gae *GAEHttpConnection) handleHttpRes(conn *SessionConnection, req *event.HTTPRequestEvent, ev *event.HTTPResponseEvent) (*http.Response, error) {
	originRange := req.RawReq.Header.Get("Range")
	contentRange := ev.GetHeader("Content-Range")
	if ev.Status == 206 && len(contentRange) > 0 && strings.EqualFold(req.Method, "GET") {
		_, end, length := util.ParseContentRangeHeaderValue(contentRange)
		if len(originRange) > 0 {
			_, oe := util.ParseRangeHeaderValue(originRange)
			if oe > 0 {
				length = oe + 1
			}
		}
		if length > end+1 {
			gae.doRangeFetch(req.RawReq, ev.ToResponse())
			return nil, nil
		}
		if len(originRange) == 0 {
			ev.Status = 200
			ev.RemoveHeader("Content-Range")
		}
	}
	httpres := ev.ToResponse()
	err := httpres.Write(conn.LocalRawConn)
	return httpres, err
}
Example #2
0
func (r *rangeFetchTask) processResponse(res *http.Response) error {
	if r.closed {
		return fmt.Errorf("Session[%d] already closed for handling range response.", r.SessionID)
	}
	if nil != r.TaskValidation {
		if !r.TaskValidation() {
			r.Close()
			return fmt.Errorf("Task ternminated by callback")
		}
	}
	if r.rangeState != STATE_WAIT_NORMAL_RES && res.StatusCode != 206 {
		return fmt.Errorf("Expected 206 response, but got %d", res.StatusCode)
	}
	switch r.rangeState {
	case STATE_WAIT_NORMAL_RES:
		r.res = res
		return nil
	case STATE_WAIT_HEAD_RES:
		contentRangeHeader := res.Header.Get("Content-Range")
		if len(contentRangeHeader) > 0 {
			_, _, length := util.ParseContentRangeHeaderValue(contentRangeHeader)
			res.ContentLength = int64(length)
		}
		if r.contentEnd == -1 {
			r.contentEnd = int(res.ContentLength) - 1
			r.originRangeHader = ""
		}
		resbody := res.Body
		r.res = res
		r.res.Request = r.req
		if r.res.StatusCode < 300 {
			if len(r.originRangeHader) > 0 {
				r.res.StatusCode = 206
				r.res.Status = ""
				r.res.Header.Set("Content-Range", fmt.Sprintf("bytes %d-%d/%d", r.contentBegin, r.contentEnd, res.ContentLength))
			} else {
				r.res.StatusCode = 200
				r.res.Status = ""
				r.res.Header.Del("Content-Range")
			}
			res.ContentLength = int64(r.contentEnd - r.contentBegin + 1)
			res.Header.Set("Content-Length", fmt.Sprintf("%d", res.ContentLength))
			rb := newRangeBody()
			r.res.Body = rb
		}
		log.Printf("Session[%d]Recv first range chunk:%s, %d %d ", r.SessionID, contentRangeHeader, r.contentEnd, r.contentBegin)
		if nil != resbody && r.res.StatusCode < 300 {
			var n int
			rb := r.res.Body.(*rangeBody)
			tmpbuf, ok := resbody.(*util.BufferCloseWrapper)
			if ok {
				n = tmpbuf.Buf.Len()
				rb.buf = tmpbuf.Buf
			} else {
				nn, _ := io.Copy(rb.buf, resbody)
				n = int(nn)
			}
			r.expectedRangePos += int(n)
			r.rangePos += int(n)
		}
		return nil
	case STATE_WAIT_RANGE_GET_RES:
		if nil == res.Body {
			return fmt.Errorf("Nil body for response:%d", res.StatusCode)
		}
		contentRange := res.Header.Get("Content-Range")
		start, _, _ := util.ParseContentRangeHeaderValue(contentRange)
		log.Printf("Session[%d]Recv range chunk:%s", r.SessionID, contentRange)
		body := r.res.Body.(*rangeBody)
		r.chunkMutex.Lock()
		if start == r.expectedRangePos {
			r.expectedRangePos += body.WriteHttpBody(res.Body)
		} else {
			r.chunks[start] = res.Body
		}
		for {
			if chunk, exist := r.chunks[r.expectedRangePos]; exist {
				delete(r.chunks, r.expectedRangePos)
				r.expectedRangePos += body.WriteHttpBody(chunk)
			} else {
				if r.expectedRangePos < r.contentEnd {
					log.Printf("Session[%d]Expect range chunk:%d\n", r.SessionID, r.expectedRangePos)
				} else {
					body.c <- nil
				}
				break
			}
		}
		r.chunkMutex.Unlock()
	}
	return nil
}