8000 fix(net): unexpected write (#8291 close #8281) · AlistGo/alist@a2f2662 · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Commit a2f2662

Browse files
authored
fix(net): unexpected write (#8291 close #8281)
1 parent a4bfbf8 commit a2f2662

File tree

4 files changed

+59
-39
lines changed

4 files changed

+59
-39
lines changed

internal/net/serve.go

+9-7
Original file line numberDiff line numberDiff line change
@@ -52,19 +52,19 @@ import (
5252
//
5353
// If the caller has set w's ETag header formatted per RFC 7232, section 2.3,
5454
// ServeHTTP uses it to handle requests using If-Match, If-None-Match, or If-Range.
55-
func ServeHTTP(w http.ResponseWriter, r *http.Request, name string, modTime time.Time, size int64, RangeReadCloser model.RangeReadCloserIF) {
55+
func ServeHTTP(w http.ResponseWriter, r *http.Request, name string, modTime time.Time, size int64, RangeReadCloser model.RangeReadCloserIF) error {
5656
defer RangeReadCloser.Close()
5757
setLastModified(w, modTime)
5858
done, rangeReq := checkPreconditions(w, r, modTime)
5959
if done {
60-
return
60+
return nil
6161
}
6262

6363
if size < 0 {
6464
// since too many functions need file size to work,
6565
// will not implement the support of unknown file size here
6666
http.Error(w, "negative content size not supported", http.StatusInternalServerError)
67-
return
67+
return nil
6868
}
6969

7070
code := http.StatusOK
@@ -103,7 +103,7 @@ func ServeHTTP(w http.ResponseWriter, r *http.Request, name string, modTime time
103103
fallthrough
104104
default:
105105
http.Error(w, err.Error(), http.StatusRequestedRangeNotSatisfiable)
106-
return
106+
return nil
107107
}
108108

109109
if sumRangesSize(ranges) > size {
@@ -124,7 +124,7 @@ func ServeHTTP(w http.ResponseWriter, r *http.Request, name string, modTime time
124124
code = http.StatusTooManyRequests
125125
}
126126
http.Error(w, err.Error(), code)
127-
return
127+
return nil
128128
}
129129
sendContent = reader
130130
case len(ranges) == 1:
@@ -147,7 +147,7 @@ func ServeHTTP(w http.ResponseWriter, r *http.Request, name string, modTime time
147147
code = http.StatusTooManyRequests
148148
}
149149
http.Error(w, err.Error(), code)
150-
return
150+
return nil
151151
}
152152
sendSize = ra.Length
153153
code = http.StatusPartialContent
@@ -205,9 +205,11 @@ func ServeHTTP(w http.ResponseWriter, r *http.Request, name string, modTime time
205205
if err == ErrExceedMaxConcurrency {
206206
code = http.StatusTooManyRequests
207207
}
208-
http.Error(w, err.Error(), code)
208+
w.WriteHeader(code)
209+
return err
209210
}
210211
}
212+
return nil
211213
}
212214
func ProcessHeader(origin, override http.Header) http.Header {
213215
result := http.Header{}

server/common/proxy.go

+29-8
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,10 @@ func Proxy(w http.ResponseWriter, r *http.Request, link *model.Link, file model.
3939
return nil
4040
} else if link.RangeReadCloser != nil {
4141
attachHeader(w, file)
42-
net.ServeHTTP(w, r, file.GetName(), file.ModTime(), file.GetSize(), &stream.RateLimitRangeReadCloser{
42+
return net.ServeHTTP(w, r, file.GetName(), file.ModTime(), file.GetSize(), &stream.RateLimitRangeReadCloser{
4343
RangeReadCloserIF: link.RangeReadCloser,
4444
Limiter: stream.ServerDownloadLimit,
4545
})
46-
return nil
4746
} else if link.Concurrency != 0 || link.PartSize != 0 {
4847
attachHeader(w, file)
4948
size := file.GetSize()
@@ -66,11 +65,10 @@ func Proxy(w http.ResponseWriter, r *http.Request, link *model.Link, file model.
6665
rc, err := down.Download(ctx, req)
6766
return rc, err
6867
}
69-
net.ServeHTTP(w, r, file.GetName(), file.ModTime(), file.GetSize(), &stream.RateLimitRangeReadCloser{
68+
return net.ServeHTTP(w, r, file.GetName(), file.ModTime(), file.GetSize(), &stream.RateLimitRangeReadCloser{
7069
RangeReadCloserIF: &model.RangeReadCloser{RangeReader: rangeReader},
7170
Limiter: stream.ServerDownloadLimit,
7271
})
73-
return nil
7472
} else {
7573
//transparent proxy
7674
header := net.ProcessHeader(r.Header, link.Header)
@@ -90,10 +88,7 @@ func Proxy(w http.ResponseWriter, r *http.Request, link *model.Link, file model.
9088
Limiter: stream.ServerDownloadLimit,
9189
Ctx: r.Context(),
9290
})
93-
if err != nil {
94-
return err
95-
}
96-
return nil
91+
return err
9792
}
9893
}
9994
func attachHeader(w http.ResponseWriter, file model.Obj) {
@@ -133,3 +128,29 @@ func ProxyRange(link *model.Link, size int64) {
133128
link.RangeReadCloser = nil
134129
}
135130
}
131+
132+
type InterceptResponseWriter struct {
133+
http.ResponseWriter
134+
io.Writer
135+
}
136+
137+
func (iw *InterceptResponseWriter) Write(p []byte) (int, error) {
138+
return iw.Writer.Write(p)
139+
}
140+
141+
type WrittenResponseWriter struct {
142+
http.ResponseWriter
143+
written bool
144+
}
145+
146+
func (ww *WrittenResponseWriter) Write(p []byte) (int, error) {
147+
n, err := ww.ResponseWriter.Write(p)
148+
if !ww.written && n > 0 {
149+
ww.written = true
150+
}
151+
return n, err
152+
}
153+
154+
func (ww *WrittenResponseWriter) IsWritten() bool {
155+
return ww.written
156+
}

server/handles/down.go

+15-20
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"bytes"
55
"fmt"
66
"io"
7-
"net/http"
87
stdpath "path"
98
"strconv"
109
"strings"
@@ -129,15 +128,16 @@ func localProxy(c *gin.Context, link *model.Link, file model.Obj, proxyRange boo
129128
if proxyRange {
130129
common.ProxyRange(link, file.GetSize())
131130
}
131+
Writer := &common.WrittenResponseWriter{ResponseWriter: c.Writer}
132132

133133
//优先处理md文件
134134
if utils.Ext(file.GetName()) == "md" && setting.GetBool(conf.FilterReadMeScripts) {
135-
w := c.Writer
136135
buf := bytes.NewBuffer(make([]byte, 0, file.GetSize()))
137-
err = common.Proxy(&proxyResponseWriter{ResponseWriter: w, Writer: buf}, c.Request, link, file)
136+
w := &common.InterceptResponseWriter{ResponseWriter: Writer, Writer: buf}
137+
err = common.Proxy(w, c.Request, link, file)
138138
if err == nil && buf.Len() > 0 {
139-
if w.Status() < 200 || w.Status() > 300 {
140-
w.Write(buf.Bytes())
139+
if c.Writer.Status() < 200 || c.Writer.Status() > 300 {
140+
c.Writer.Write(buf.Bytes())
141141
return
142142
}
143143

@@ -148,19 +148,23 @@ func localProxy(c *gin.Context, link *model.Link, file model.Obj, proxyRange boo
148148
buf.Reset()
149149
err = bluemonday.UGCPolicy().SanitizeReaderToWriter(&html, buf)
150150
if err == nil {
151-
w.Header().Set("Content-Length", strconv.FormatInt(int64(buf.Len()), 10))
152-
w.Header().Set("Content-Type", "text/html; charset=utf-8")
153-
_, err = utils.CopyWithBuffer(c.Writer, buf)
151+
Writer.Header().Set("Content-Length", strconv.FormatInt(int64(buf.Len()), 10))
152+
Writer.Header().Set("Content-Type", "text/html; charset=utf-8")
153+
_, err = utils.CopyWithBuffer(Writer, buf)
154154
}
155155
}
156156
}
157157
} else {
158-
err = common.Proxy(c.Writer, c.Request, link, file)
158+
err = common.Proxy(Writer, c.Request, link, file)
159159
}
160-
if err != nil {
161-
common.ErrorResp(c, err, 500, true)
160+
if err == nil {
162161
return
163162
}
163+
if Writer.IsWritten() {
164+
log.Errorf("%s %s local proxy error: %+v", c.Request.Method, c.Request.URL.Path, err)
165+
} else {
166+
common.ErrorResp(c, err, 500, true)
167+
}
164168
}
165169

166170
// TODO need optimize
@@ -182,12 +186,3 @@ func canProxy(storage driver.Driver, filename string) bool {
182186
}
183187
return false
184188
}
185-
186-
type proxyResponseWriter struct {
187-
http.ResponseWriter
188-
io.Writer
189-
}
190-
191-
func (pw *proxyResponseWriter) Write(p []byte) (int, error) {
192-
return pw.Writer.Write(p)
193-
}

server/webdav/webdav.go

+6-4
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import (
2424
"github.com/alist-org/alist/v3/internal/sign"
2525
"github.com/alist-org/alist/v3/pkg/utils"
2626
"github.com/alist-org/alist/v3/server/common"
27-
log "github.com/sirupsen/logrus"
2827
)
2928

3029
type Handler struct {
@@ -59,7 +58,11 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
5958
status, err = h.handleOptions(brw, r)
6059
case "GET", "HEAD", "POST":
6160
useBufferedWriter = false
62-
status, err = h.handleGetHeadPost(w, r)
61+
Writer := &common.WrittenResponseWriter{ResponseWriter: w}
62+
status, err = h.handleGetHeadPost(Writer, r)
63+
if status != 0 && Writer.IsWritten() {
64+
status = 0
65+
}
6366
case "DELETE":
6467
status, err = h.handleDelete(brw, r)
6568
case "PUT":
@@ -247,8 +250,7 @@ func (h *Handler) handleGetHeadPost(w http.ResponseWriter, r *http.Request) (sta
247250
}
248251
err = common.Proxy(w, r, link, fi)
249252
if err != nil {
250-
log.Errorf("webdav proxy error: %+v", err)
251-
return http.StatusInternalServerError, err
253+
return http.StatusInternalServerError, fmt.Errorf("webdav proxy error: %+v", err)
252254
}
253255
} else if storage.GetStorage().WebdavProxy() && downProxyUrl != "" {
254256
u := fmt.Sprintf("%s%s?sign=%s",

0 commit comments

Comments
 (0)
0