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") ...
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()