JobServer
Landscape
JobServer 包含 Schedulers 及 Workers。Scheduler 中包含一组 Scheduler 实例,用于定时调度 Job。Workers 包含了固定种类的 Worker 实例,每个实例独自工作。JobServer 用于创建、查询、更改 Job 状态,并持久化到 Store 中。
Worker 的实现通过向 JobServer 注册 Worker Generator 来实现。具体的实现不在开源项目中。同时,Worker 与 Scheduler 成对出现,均由使用者自己实现,因此,细节不能继续讨论。
var accountMigrationInterface func(*Server) einterfaces.AccountMigrationInterface
func RegisterAccountMigrationInterface(f func(*Server) einterfaces.AccountMigrationInterface) {
accountMigrationInterface = f
}
HTTPService
Landscape
Core
首先创建基础的 Dialer 结构,并配置参数。
dialContext := (&net.Dialer{
Timeout: ConnectTimeout,
KeepAlive: 30 * time.Second,
}).DialContext
将基础的 DialContext 传入,进行增强后,返回新的 DialContext。
func dialContextFilter(dial DialContextFunction, allowHost func(host string) bool, allowIP func(ip net.IP) bool) DialContextFunction {
return func(ctx context.Context, network, addr string) (net.Conn, error) {
host, port, err := net.SplitHostPort(addr)
if err != nil {
return nil, err
}
if allowHost != nil && allowHost(host) {
return dial(ctx, network, addr)
}
ips, err := net.LookupIP(host)
if err != nil {
return nil, err
}
var firstErr error
for _, ip := range ips {
select {
case <-ctx.Done():
return nil, ctx.Err()
default:
}
if allowIP == nil || !allowIP(ip) {
continue
}
conn, err := dial(ctx, network, net.JoinHostPort(ip.String(), port))
if err == nil {
return conn, nil
}
if firstErr == nil {
firstErr = err
}
}
if firstErr == nil {
return nil, AddressForbidden
}
return nil, firstErr
}
}
File Store
Landscape
FileBackend 接口如下
type FileBackend interface {
TestConnection() *model.AppError
Reader(path string) (ReadCloseSeeker, *model.AppError)
ReadFile(path string) ([]byte, *model.AppError)
FileExists(path string) (bool, *model.AppError)
CopyFile(oldPath, newPath string) *model.AppError
MoveFile(oldPath, newPath string) *model.AppError
WriteFile(fr io.Reader, path string) (int64, *model.AppError)
RemoveFile(path string) *model.AppError
ListDirectory(path string) (*[]string, *model.AppError)
RemoveDirectory(path string) *model.AppError
}
Image Proxy
References
- willnorris/imageproxy: A caching, resizing image proxy written in Go
Landscape
Details
LocalBackend 获取图片的处理,注意其中的 Headers。
func (backend *LocalBackend) GetImage(w http.ResponseWriter, r *http.Request, imageURL string) {
// The interface to the proxy only exposes a ServeHTTP method, so fake a request to it
req, err := http.NewRequest(http.MethodGet, "/"+imageURL, nil)
if err != nil {
// http.NewRequest should only return an error on an invalid URL
mlog.Error("Failed to create request for proxied image", mlog.String("url", imageURL), mlog.Err(err))
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte{})
return
}
w.Header().Set("X-Frame-Options", "deny")
w.Header().Set("X-XSS-Protection", "1; mode=block")
w.Header().Set("X-Content-Type-Options", "nosniff")
w.Header().Set("Content-Security-Policy", "default-src 'none'; img-src data:; style-src 'unsafe-inline'")
backend.impl.ServeHTTP(w, req)
}