Функция http.ServeContent
Функция http.ServeContent используется для отправки содержимого в HTTP-ответе.
В первый параметр передается http.ResponseWriter для записи ответа,
во второй параметр — *http.Request для получения информации о запросе,
в третий параметр — имя файла в виде строки,
в четвертый параметр — время модификации содержимого,
в пятый параметр — объект типа io.ReadSeeker, содержимое которого будет отправлено.
Синтаксис
http.ServeContent(w http.ResponseWriter, r *http.Request, name string, modtime time.Time, content io.ReadSeeker)
Пример с файлом
Давайте отправим содержимое файла в ответ на HTTP-запрос:
package main
import (
"net/http"
"os"
"time"
)
func main() {
http.HandleFunc("/file", func(w http.ResponseWriter, r *http.Request) {
file, err := os.Open("example.txt")
if err != nil {
http.Error(w, "File not found", http.StatusNotFound)
return
}
defer file.Close()
stat, err := file.Stat()
if err != nil {
http.Error(w, "File error", http.StatusInternalServerError)
return
}
http.ServeContent(w, r, stat.Name(), stat.ModTime(), file)
})
http.ListenAndServe(":8080", nil)
}
В этом примере открывается файл example.txt, и его содержимое отправляется клиенту.
Функция автоматически обрабатывает заголовки кэширования и поддерживает частичную загрузку.
Пример с данными в памяти
Давайте отправим содержимое из памяти, используя bytes.NewReader:
package main
import (
"bytes"
"fmt"
"net/http"
"time"
)
func main() {
http.HandleFunc("/data", func(w http.ResponseWriter, r *http.Request) {
data := []byte("Hello, World!")
reader := bytes.NewReader(data)
modTime := time.Now()
http.ServeContent(w, r, "data.txt", modTime, reader)
})
fmt.Println("Server started on :8080")
http.ListenAndServe(":8080", nil)
}
В этом примере данные хранятся в памяти, но функция http.ServeContent обрабатывает их так же,
как если бы они были из файла. Это полезно для динамически генерируемого контента.
Пример с условными запросами
Функция автоматически обрабатывает заголовки If-Modified-Since и If-None-Match.
Давайте проверим это на примере:
package main
import (
"bytes"
"fmt"
"net/http"
"time"
)
func main() {
http.HandleFunc("/static", func(w http.ResponseWriter, r *http.Request) {
content := []byte("Static content")
reader := bytes.NewReader(content)
modTime := time.Now().Add(-24 * time.Hour)
http.ServeContent(w, r, "static.txt", modTime, reader)
})
fmt.Println("Server started on :8080")
http.ListenAndServe(":8080", nil)
}
При повторном запросе браузер отправит заголовок If-Modified-Since,
и если содержимое не изменилось, сервер ответит статусом 304 Not Modified,
что экономит трафик.
Пример с частичной загрузкой (Range запросы)
Функция поддерживает заголовок Range, позволяя клиенту загружать файл по частям:
package main
import (
"bytes"
"fmt"
"net/http"
"time"
)
func main() {
http.HandleFunc("/video", func(w http.ResponseWriter, r *http.Request) {
videoData := bytes.Repeat([]byte("video data "), 100)
reader := bytes.NewReader(videoData)
modTime := time.Now()
http.ServeContent(w, r, "video.mp4", modTime, reader)
})
fmt.Println("Server started on :8080")
http.ListenAndServe(":8080", nil)
}
Если клиент отправит заголовок Range: bytes=0-99, сервер вернет только первые 100 байт.
Это особенно полезно для стриминга видео и возобновления загрузок.
Смотрите также
-
функцию
http.ServeFile,
которая упрощает отправку файлов без ручного открытия -
функцию
http.FileServer,
которая создает обработчик для целого каталога файлов -
структуру
http.ServeMux,
которая используется для маршрутизации HTTP-запросов -
функцию
http.NotFound,
которая возвращает клиенту ошибку 404 Not Found