(filename string, instances int, logger *clog.CondLogger, next Filter)
| 26 | } |
| 27 | |
| 28 | func NewJSFilter(filename string, instances int, logger *clog.CondLogger, next Filter) (*JSFilter, error) { |
| 29 | script, err := os.ReadFile(filename) |
| 30 | if err != nil { |
| 31 | return nil, fmt.Errorf("unable to load JS script file %q: %w", filename, err) |
| 32 | } |
| 33 | |
| 34 | instances = max(1, instances) |
| 35 | pool := make(chan JSFilterFunc, instances) |
| 36 | initGroup, _ := errgroup.WithContext(context.Background()) |
| 37 | |
| 38 | for i := 0; i < instances; i++ { |
| 39 | initGroup.Go(func() error { |
| 40 | vm := goja.New() |
| 41 | err := jsext.AddPrinter(vm, logger) |
| 42 | if err != nil { |
| 43 | return fmt.Errorf("can't add print function to runtime: %w", err) |
| 44 | } |
| 45 | err = jsext.ConfigureRuntime(vm) |
| 46 | if err != nil { |
| 47 | return fmt.Errorf("can't configure runtime: %w", err) |
| 48 | } |
| 49 | _, err = vm.RunString(string(script)) |
| 50 | if err != nil { |
| 51 | return fmt.Errorf("script run failed: %w", err) |
| 52 | } |
| 53 | |
| 54 | var f JSFilterFunc |
| 55 | var accessFnJSVal goja.Value |
| 56 | if ex := vm.Try(func() { |
| 57 | accessFnJSVal = vm.Get("access") |
| 58 | }); ex != nil { |
| 59 | return fmt.Errorf("\"access\" function cannot be located in VM context: %w", err) |
| 60 | } |
| 61 | if accessFnJSVal == nil { |
| 62 | return errors.New("\"access\" function is not defined") |
| 63 | } |
| 64 | err = vm.ExportTo(accessFnJSVal, &f) |
| 65 | if err != nil { |
| 66 | return fmt.Errorf("can't export \"access\" function from JS VM: %w", err) |
| 67 | } |
| 68 | |
| 69 | pool <- f |
| 70 | return nil |
| 71 | }) |
| 72 | } |
| 73 | |
| 74 | err = initGroup.Wait() |
| 75 | if err != nil { |
| 76 | return nil, err |
| 77 | } |
| 78 | |
| 79 | return &JSFilter{ |
| 80 | funcPool: pool, |
| 81 | next: next, |
| 82 | }, nil |
| 83 | } |
| 84 | |
| 85 | func (j *JSFilter) Access(ctx context.Context, req *http.Request, username, network, address string) error { |
no test coverage detected