// materializeFile takes a physical file or stream (named pipe, user input, // ...) and returns an io.Reader and the number of bytes that can be read // from it. func materializeFile(log *logging.Logger, f *os.File) (io.Reader, int64, error) { fi, err := f.Stat() if err != nil { return nil, 0, err } // If the file is actually a char device (like user typed input) // or a named pipe (like a streamed in file), buffer it up. // // When uploading a file, you need to either explicitly set the // Content-Length header or send a chunked request. Since the // github upload server doesn't accept chunked encoding, we have // to set the size of the file manually. Since a stream doesn't have a // predefined length, it's read entirely into a byte buffer. if fi.Mode()&(os.ModeCharDevice|os.ModeNamedPipe) == 1 { log.Debug("input was a stream, buffering up") var buf bytes.Buffer n, err := buf.ReadFrom(f) if err != nil { return nil, 0, errors.New("req: could not buffer up input stream: " + err.Error()) } return &buf, n, err } // We know the os.File is most likely an actual file now. n, err := GetFileSize(f) return f, n, err }
// Execute a given command without waiting for its result. func ExecDetached(log *log.Logger, cmdName string, arguments ...string) error { if log != nil { log.Debug("Running %s %v", cmdName, arguments) } cmd := exec.Command(cmdName, arguments...) return cmd.Start() }
func buildDispatcher( startup *StartupConfig, cfg *config.Configuration, consul *api.Client, handler *proxy.ProxyHandler, rpool *redis.Pool, logger *logging.Logger, lastIndex uint64, ) (dispatcher.Dispatcher, uint64, error) { var disp dispatcher.Dispatcher var err error var meta *api.QueryMeta var configs api.KVPairs var localCfg config.Configuration = *cfg var appCfgs map[string]config.Application = make(map[string]config.Application) dispLogger := logging.MustGetLogger("dispatch") switch startup.DispatchingMode { case "path": disp, err = dispatcher.NewPathBasedDispatcher(&localCfg, dispLogger, handler) case "host": disp, err = dispatcher.NewHostBasedDispatcher(&localCfg, dispLogger, handler) default: err = fmt.Errorf("unsupported dispatching mode: '%s'", startup.DispatchingMode) } if err != nil { return nil, 0, fmt.Errorf("error while creating proxy builder: %s", err) } applicationConfigBase := startup.ConsulBaseKey + "/applications" queryOpts := api.QueryOptions{ WaitIndex: lastIndex, WaitTime: 30 * time.Minute, } logger.Info("loading gateway config from KV %s", startup.ConsulBaseKey) configs, meta, err = consul.KV().List(startup.ConsulBaseKey, &queryOpts) if err != nil { return nil, 0, err } for _, cfgKVPair := range configs { logger.Debug("found KV pair with key '%s'", cfgKVPair.Key) switch strings.TrimPrefix(startup.ConsulBaseKey+"/", cfgKVPair.Key) { case "authentication": if err := json.Unmarshal(cfgKVPair.Value, &localCfg.Authentication); err != nil { return nil, meta.LastIndex, fmt.Errorf("JSON error on consul KV pair '%s': %s", cfgKVPair.Key, err) } case "rate_limiting": if err := json.Unmarshal(cfgKVPair.Value, &localCfg.RateLimiting); err != nil { return nil, meta.LastIndex, fmt.Errorf("JSON error on consul KV pair '%s': %s", cfgKVPair.Key, err) } } if strings.HasPrefix(cfgKVPair.Key, applicationConfigBase) { var appCfg config.Application if err := json.Unmarshal(cfgKVPair.Value, &appCfg); err != nil { return nil, meta.LastIndex, fmt.Errorf("JSON error on consul KV pair '%s': %s", cfgKVPair.Key, err) } name := strings.TrimPrefix(cfgKVPair.Key, applicationConfigBase+"/") appCfgs[name] = appCfg } } authHandler, err := auth.NewAuthDecorator(&localCfg.Authentication, rpool, logging.MustGetLogger("auth"), startup.UiDir) if err != nil { return nil, meta.LastIndex, err } rlim, err := ratelimit.NewRateLimiter(localCfg.RateLimiting, rpool, logging.MustGetLogger("ratelimiter")) if err != nil { logger.Fatal(fmt.Sprintf("error while configuring rate limiting: %s", err)) } cch := cache.NewCache(4096) // Order is important here! Behaviours will be called in LIFO order; // behaviours that are added last will be called first! disp.AddBehaviour(dispatcher.NewCachingBehaviour(cch)) disp.AddBehaviour(dispatcher.NewAuthenticationBehaviour(authHandler)) disp.AddBehaviour(dispatcher.NewRatelimitBehaviour(rlim)) for name, appCfg := range appCfgs { logger.Info("registering application '%s' from Consul", name) if err := disp.RegisterApplication(name, appCfg); err != nil { return nil, meta.LastIndex, err } } for name, appCfg := range localCfg.Applications { logger.Info("registering application '%s' from local config", name) if err := disp.RegisterApplication(name, appCfg); err != nil { return nil, meta.LastIndex, err } } if err = disp.Initialize(); err != nil { return nil, meta.LastIndex, err } return disp, meta.LastIndex, nil }