Source File
filetransport.go
Belonging Package
net/http
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package http
import (
)
// fileTransport implements RoundTripper for the 'file' protocol.
type fileTransport struct {
fh fileHandler
}
// NewFileTransport returns a new [RoundTripper], serving the provided
// [FileSystem]. The returned RoundTripper ignores the URL host in its
// incoming requests, as well as most other properties of the
// request.
//
// The typical use case for NewFileTransport is to register the "file"
// protocol with a [Transport], as in:
//
// t := &http.Transport{}
// t.RegisterProtocol("file", http.NewFileTransport(http.Dir("/")))
// c := &http.Client{Transport: t}
// res, err := c.Get("file:///etc/passwd")
// ...
func ( FileSystem) RoundTripper {
return fileTransport{fileHandler{}}
}
// NewFileTransportFS returns a new [RoundTripper], serving the provided
// file system fsys. The returned RoundTripper ignores the URL host in its
// incoming requests, as well as most other properties of the
// request. The files provided by fsys must implement [io.Seeker].
//
// The typical use case for NewFileTransportFS is to register the "file"
// protocol with a [Transport], as in:
//
// fsys := os.DirFS("/")
// t := &http.Transport{}
// t.RegisterProtocol("file", http.NewFileTransportFS(fsys))
// c := &http.Client{Transport: t}
// res, err := c.Get("file:///etc/passwd")
// ...
func ( fs.FS) RoundTripper {
return NewFileTransport(FS())
}
func ( fileTransport) ( *Request) ( *Response, error) {
// We start ServeHTTP in a goroutine, which may take a long
// time if the file is large. The newPopulateResponseWriter
// call returns a channel which either ServeHTTP or finish()
// sends our *Response on, once the *Response itself has been
// populated (even if the body itself is still being
// written to the res.Body, a pipe)
, := newPopulateResponseWriter()
go func() {
.fh.ServeHTTP(, )
.finish()
}()
return <-, nil
}
func () (*populateResponse, <-chan *Response) {
, := io.Pipe()
:= &populateResponse{
ch: make(chan *Response),
pw: ,
res: &Response{
Proto: "HTTP/1.0",
ProtoMajor: 1,
Header: make(Header),
Close: true,
Body: ,
},
}
return , .ch
}
// populateResponse is a ResponseWriter that populates the *Response
// in res, and writes its body to a pipe connected to the response
// body. Once writes begin or finish() is called, the response is sent
// on ch.
type populateResponse struct {
res *Response
ch chan *Response
wroteHeader bool
hasContent bool
sentResponse bool
pw *io.PipeWriter
}
func ( *populateResponse) () {
if !.wroteHeader {
.WriteHeader(500)
}
if !.sentResponse {
.sendResponse()
}
.pw.Close()
}
func ( *populateResponse) () {
if .sentResponse {
return
}
.sentResponse = true
if .hasContent {
.res.ContentLength = -1
}
.ch <- .res
}
func ( *populateResponse) () Header {
return .res.Header
}
func ( *populateResponse) ( int) {
if .wroteHeader {
return
}
.wroteHeader = true
.res.StatusCode =
.res.Status = fmt.Sprintf("%d %s", , StatusText())
}
func ( *populateResponse) ( []byte) ( int, error) {
if !.wroteHeader {
.WriteHeader(StatusOK)
}
.hasContent = true
if !.sentResponse {
.sendResponse()
}
return .pw.Write()
}
The pages are generated with Golds v0.7.6. (GOOS=linux GOARCH=amd64)