/
dimamir
/
rill
Обзор
Документация
Войти
/
dimamir
/
rill
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
runtime/drivers/https/https.go
254 строки
6 KB
Eric P Green
Fix/Refactor the "Add data" forms (#5162)
24 июл 2024, 15:36
Не верифицирован
24 июл 2024, 15:36
09ed457
Код
Авторство
О чём код?
package https import ( "context" "errors" "fmt" "net/http" "net/url" "time" "github.com/mitchellh/mapstructure" "github.com/rilldata/rill/runtime/drivers" "github.com/rilldata/rill/runtime/pkg/activity" "github.com/rilldata/rill/runtime/pkg/fileutil" "go.uber.org/zap" ) func init() { drivers.Register("https", driver{}) drivers.RegisterAsConnector("https", driver{}) } var spec = drivers.Spec{ DisplayName: "https", Description: "Connect to a remote file.", SourceProperties: []*drivers.PropertySpec{ { Key: "path", Type: drivers.StringPropertyType, DisplayName: "Path", Description: "Path to the remote file.", Placeholder: "https://example.com/file.csv", Required: true, }, { Key: "name", Type: drivers.StringPropertyType, DisplayName: "Source name", Description: "The name of the source", Placeholder: "my_new_source", Required: true, }, }, ImplementsFileStore: true, } type driver struct{} func (d driver) Open(instanceID string, config map[string]any, client *activity.Client, logger *zap.Logger) (drivers.Handle, error) { if instanceID == "" { return nil, errors.New("https driver can't be shared") } conn := &connection{ config: config, logger: logger, } return conn, nil } func (d driver) Spec() drivers.Spec { return spec } func (d driver) HasAnonymousSourceAccess(ctx context.Context, src map[string]any, logger *zap.Logger) (bool, error) { return true, nil } func (d driver) TertiarySourceConnectors(ctx context.Context, src map[string]any, logger *zap.Logger) ([]string, error) { return nil, nil } type sourceProperties struct { Path string `mapstructure:"path"` URI string `mapstructure:"uri"` Headers map[string]string `mapstructure:"headers"` } func parseSourceProperties(props map[string]any) (*sourceProperties, error) { conf := &sourceProperties{} err := mapstructure.Decode(props, conf) if err != nil { return nil, err } // Backwards compatibility for "uri" renamed to "path" if conf.URI != "" { conf.Path = conf.URI } return conf, nil } type connection struct { config map[string]any logger *zap.Logger } var _ drivers.Handle = &connection{} // Ping implements drivers.Handle. func (c *connection) Ping(ctx context.Context) error { return drivers.ErrNotImplemented } // Driver implements drivers.Connection. func (c *connection) Driver() string { return "https" } // Config implements drivers.Connection. func (c *connection) Config() map[string]any { return c.config } // Close implements drivers.Connection. func (c *connection) Close() error { return nil } // AsRegistry implements drivers.Connection. func (c *connection) AsRegistry() (drivers.RegistryStore, bool) { return nil, false } // AsCatalogStore implements drivers.Connection. func (c *connection) AsCatalogStore(instanceID string) (drivers.CatalogStore, bool) { return nil, false } // AsRepoStore implements drivers.Connection. func (c *connection) AsRepoStore(instanceID string) (drivers.RepoStore, bool) { return nil, false } // AsAdmin implements drivers.Handle. func (c *connection) AsAdmin(instanceID string) (drivers.AdminService, bool) { return nil, false } // AsOLAP implements drivers.Connection. func (c *connection) AsOLAP(instanceID string) (drivers.OLAPStore, bool) { return nil, false } // AsAI implements drivers.Handle. func (c *connection) AsAI(instanceID string) (drivers.AIService, bool) { return nil, false } // Migrate implements drivers.Connection. func (c *connection) Migrate(ctx context.Context) (err error) { return nil } // MigrationStatus implements drivers.Connection. func (c *connection) MigrationStatus(ctx context.Context) (current, desired int, err error) { return 0, 0, nil } // AsObjectStore implements drivers.Connection. func (c *connection) AsObjectStore() (drivers.ObjectStore, bool) { return nil, false } // AsModelExecutor implements drivers.Handle. func (c *connection) AsModelExecutor(instanceID string, opts *drivers.ModelExecutorOptions) (drivers.ModelExecutor, bool) { return nil, false } // AsModelManager implements drivers.Handle. func (c *connection) AsModelManager(instanceID string) (drivers.ModelManager, bool) { return nil, false } // AsTransporter implements drivers.Connection. func (c *connection) AsTransporter(from, to drivers.Handle) (drivers.Transporter, bool) { return nil, false } func (c *connection) AsFileStore() (drivers.FileStore, bool) { return c, true } // AsWarehouse implements drivers.Handle. func (c *connection) AsWarehouse() (drivers.Warehouse, bool) { return nil, false } // AsSQLStore implements drivers.Connection. func (c *connection) AsSQLStore() (drivers.SQLStore, bool) { return nil, false } // AsNotifier implements drivers.Connection. func (c *connection) AsNotifier(properties map[string]any) (drivers.Notifier, error) { return nil, drivers.ErrNotNotifier } // FilePaths implements drivers.FileStore func (c *connection) FilePaths(ctx context.Context, src map[string]any) ([]string, error) { conf, err := parseSourceProperties(src) if err != nil { return nil, fmt.Errorf("failed to parse config: %w", err) } extension, err := urlExtension(conf.Path) if err != nil { return nil, fmt.Errorf("failed to parse path %s, %w", conf.Path, err) } req, err := http.NewRequestWithContext(ctx, http.MethodGet, conf.Path, http.NoBody) if err != nil { return nil, fmt.Errorf("failed to fetch url %s: %w", conf.Path, err) } for k, v := range conf.Headers { req.Header.Set(k, v) } start := time.Now() resp, err := http.DefaultClient.Do(req) if err != nil { return nil, fmt.Errorf("failed to fetch url %s: %w", conf.Path, err) } defer resp.Body.Close() if resp.StatusCode < 200 || resp.StatusCode >= 300 { return nil, fmt.Errorf("failed to fetch url %s: %s", conf.Path, resp.Status) } file, size, err := fileutil.CopyToTempFile(resp.Body, "", extension) if err != nil { return nil, err } // Collect metrics of download size and time drivers.RecordDownloadMetrics(ctx, &drivers.DownloadMetrics{ Connector: "https", Ext: extension, Duration: time.Since(start), Size: size, }) return []string{file}, nil } func urlExtension(path string) (string, error) { u, err := url.Parse(path) if err != nil { return "", err } return fileutil.FullExt(u.Path), nil }