Use query params too for page adding handler

This commit is contained in:
2023-03-28 19:40:09 +03:00
parent 9dafdf6abf
commit be8f5e019c
10 changed files with 339 additions and 19 deletions

View File

@@ -23,11 +23,19 @@ curl -X POST --location "http://localhost:5001/pages" \
-d "{
\"url\": \"https://github.com/wkhtmltopdf/wkhtmltopdf/issues/1937\",
\"formats\": [
\"all\"
\"pdf\",
\"headers\"
]
}" | jq .
```
or
```shell
curl -X POST --location \
"http://localhost:5001/pages?url=https%3A%2F%2Fgithub.com%2Fwkhtmltopdf%2Fwkhtmltopdf%2Fissues%2F1937&formats=pdf%2Cheaders&description=Foo+Bar"
```
#### 3. Get the page's info
```shell

View File

@@ -22,6 +22,23 @@ paths:
post:
operationId: addPage
summary: Add new page
parameters:
- in: query
name: url
schema:
type: string
- in: query
name: description
schema:
type: string
- in: query
name: formats
style: form
explode: false
schema:
type: array
items:
$ref: '#/components/schemas/format'
requestBody:
content:
application/json:

View File

@@ -76,13 +76,13 @@ func (c *Client) requestURL(ctx context.Context) *url.URL {
// Add new page.
//
// POST /pages
func (c *Client) AddPage(ctx context.Context, request OptAddPageReq) (*Page, error) {
res, err := c.sendAddPage(ctx, request)
func (c *Client) AddPage(ctx context.Context, request OptAddPageReq, params AddPageParams) (*Page, error) {
res, err := c.sendAddPage(ctx, request, params)
_ = res
return res, err
}
func (c *Client) sendAddPage(ctx context.Context, request OptAddPageReq) (res *Page, err error) {
func (c *Client) sendAddPage(ctx context.Context, request OptAddPageReq, params AddPageParams) (res *Page, err error) {
otelAttrs := []attribute.KeyValue{
otelogen.OperationID("addPage"),
}
@@ -135,6 +135,67 @@ func (c *Client) sendAddPage(ctx context.Context, request OptAddPageReq) (res *P
pathParts[0] = "/pages"
uri.AddPathParts(u, pathParts[:]...)
stage = "EncodeQueryParams"
q := uri.NewQueryEncoder()
{
// Encode "url" parameter.
cfg := uri.QueryParameterEncodingConfig{
Name: "url",
Style: uri.QueryStyleForm,
Explode: true,
}
if err := q.EncodeParam(cfg, func(e uri.Encoder) error {
if val, ok := params.URL.Get(); ok {
return e.EncodeValue(conv.StringToString(val))
}
return nil
}); err != nil {
return res, errors.Wrap(err, "encode query")
}
}
{
// Encode "description" parameter.
cfg := uri.QueryParameterEncodingConfig{
Name: "description",
Style: uri.QueryStyleForm,
Explode: true,
}
if err := q.EncodeParam(cfg, func(e uri.Encoder) error {
if val, ok := params.Description.Get(); ok {
return e.EncodeValue(conv.StringToString(val))
}
return nil
}); err != nil {
return res, errors.Wrap(err, "encode query")
}
}
{
// Encode "formats" parameter.
cfg := uri.QueryParameterEncodingConfig{
Name: "formats",
Style: uri.QueryStyleForm,
Explode: false,
}
if err := q.EncodeParam(cfg, func(e uri.Encoder) error {
return e.EncodeArray(func(e uri.Encoder) error {
for i, item := range params.Formats {
if err := func() error {
return e.EncodeValue(conv.StringToString(string(item)))
}(); err != nil {
return errors.Wrapf(err, "[%d]", i)
}
}
return nil
})
}); err != nil {
return res, errors.Wrap(err, "encode query")
}
}
u.RawQuery = q.Values().Encode()
stage = "EncodeRequest"
r, err := ht.NewRequest(ctx, "POST", u, nil)
if err != nil {

View File

@@ -60,6 +60,16 @@ func (s *Server) handleAddPageRequest(args [0]string, argsEscaped bool, w http.R
ID: "addPage",
}
)
params, err := decodeAddPageParams(args, argsEscaped, r)
if err != nil {
err = &ogenerrors.DecodeParamsError{
OperationContext: opErrContext,
Err: err,
}
recordError("DecodeParams", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
request, close, err := s.decodeAddPageRequest(r)
if err != nil {
err = &ogenerrors.DecodeRequestError{
@@ -83,13 +93,26 @@ func (s *Server) handleAddPageRequest(args [0]string, argsEscaped bool, w http.R
OperationName: "AddPage",
OperationID: "addPage",
Body: request,
Params: middleware.Parameters{},
Params: middleware.Parameters{
{
Name: "url",
In: "query",
}: params.URL,
{
Name: "description",
In: "query",
}: params.Description,
{
Name: "formats",
In: "query",
}: params.Formats,
},
Raw: r,
}
type (
Request = OptAddPageReq
Params = struct{}
Params = AddPageParams
Response = *Page
)
response, err = middleware.HookMiddleware[
@@ -99,14 +122,14 @@ func (s *Server) handleAddPageRequest(args [0]string, argsEscaped bool, w http.R
](
m,
mreq,
nil,
unpackAddPageParams,
func(ctx context.Context, request Request, params Params) (response Response, err error) {
response, err = s.h.AddPage(ctx, request)
response, err = s.h.AddPage(ctx, request, params)
return response, err
},
)
} else {
response, err = s.h.AddPage(ctx, request)
response, err = s.h.AddPage(ctx, request, params)
}
if err != nil {
recordError("Internal", err)

View File

@@ -3,6 +3,7 @@
package openapi
import (
"fmt"
"net/http"
"net/url"
@@ -16,6 +17,196 @@ import (
"github.com/ogen-go/ogen/validate"
)
// AddPageParams is parameters of addPage operation.
type AddPageParams struct {
URL OptString
Description OptString
Formats []Format
}
func unpackAddPageParams(packed middleware.Parameters) (params AddPageParams) {
{
key := middleware.ParameterKey{
Name: "url",
In: "query",
}
if v, ok := packed[key]; ok {
params.URL = v.(OptString)
}
}
{
key := middleware.ParameterKey{
Name: "description",
In: "query",
}
if v, ok := packed[key]; ok {
params.Description = v.(OptString)
}
}
{
key := middleware.ParameterKey{
Name: "formats",
In: "query",
}
if v, ok := packed[key]; ok {
params.Formats = v.([]Format)
}
}
return params
}
func decodeAddPageParams(args [0]string, argsEscaped bool, r *http.Request) (params AddPageParams, _ error) {
q := uri.NewQueryDecoder(r.URL.Query())
// Decode query: url.
if err := func() error {
cfg := uri.QueryParameterDecodingConfig{
Name: "url",
Style: uri.QueryStyleForm,
Explode: true,
}
if err := q.HasParam(cfg); err == nil {
if err := q.DecodeParam(cfg, func(d uri.Decoder) error {
var paramsDotURLVal string
if err := func() error {
val, err := d.DecodeValue()
if err != nil {
return err
}
c, err := conv.ToString(val)
if err != nil {
return err
}
paramsDotURLVal = c
return nil
}(); err != nil {
return err
}
params.URL.SetTo(paramsDotURLVal)
return nil
}); err != nil {
return err
}
}
return nil
}(); err != nil {
return params, &ogenerrors.DecodeParamError{
Name: "url",
In: "query",
Err: err,
}
}
// Decode query: description.
if err := func() error {
cfg := uri.QueryParameterDecodingConfig{
Name: "description",
Style: uri.QueryStyleForm,
Explode: true,
}
if err := q.HasParam(cfg); err == nil {
if err := q.DecodeParam(cfg, func(d uri.Decoder) error {
var paramsDotDescriptionVal string
if err := func() error {
val, err := d.DecodeValue()
if err != nil {
return err
}
c, err := conv.ToString(val)
if err != nil {
return err
}
paramsDotDescriptionVal = c
return nil
}(); err != nil {
return err
}
params.Description.SetTo(paramsDotDescriptionVal)
return nil
}); err != nil {
return err
}
}
return nil
}(); err != nil {
return params, &ogenerrors.DecodeParamError{
Name: "description",
In: "query",
Err: err,
}
}
// Decode query: formats.
if err := func() error {
cfg := uri.QueryParameterDecodingConfig{
Name: "formats",
Style: uri.QueryStyleForm,
Explode: false,
}
if err := q.HasParam(cfg); err == nil {
if err := q.DecodeParam(cfg, func(d uri.Decoder) error {
return d.DecodeArray(func(d uri.Decoder) error {
var paramsDotFormatsVal Format
if err := func() error {
val, err := d.DecodeValue()
if err != nil {
return err
}
c, err := conv.ToString(val)
if err != nil {
return err
}
paramsDotFormatsVal = Format(c)
return nil
}(); err != nil {
return err
}
params.Formats = append(params.Formats, paramsDotFormatsVal)
return nil
})
}); err != nil {
return err
}
if err := func() error {
var failures []validate.FieldError
for i, elem := range params.Formats {
if err := func() error {
if err := elem.Validate(); err != nil {
return err
}
return nil
}(); err != nil {
failures = append(failures, validate.FieldError{
Name: fmt.Sprintf("[%d]", i),
Error: err,
})
}
}
if len(failures) > 0 {
return &validate.Error{Fields: failures}
}
return nil
}(); err != nil {
return err
}
}
return nil
}(); err != nil {
return params, &ogenerrors.DecodeParamError{
Name: "formats",
In: "query",
Err: err,
}
}
return params, nil
}
// GetFileParams is parameters of getFile operation.
type GetFileParams struct {
ID uuid.UUID

View File

@@ -13,7 +13,7 @@ type Handler interface {
// Add new page.
//
// POST /pages
AddPage(ctx context.Context, req OptAddPageReq) (*Page, error)
AddPage(ctx context.Context, req OptAddPageReq, params AddPageParams) (*Page, error)
// GetFile implements getFile operation.
//
// Get file content.

View File

@@ -18,7 +18,7 @@ var _ Handler = UnimplementedHandler{}
// Add new page.
//
// POST /pages
func (UnimplementedHandler) AddPage(ctx context.Context, req OptAddPageReq) (r *Page, _ error) {
func (UnimplementedHandler) AddPage(ctx context.Context, req OptAddPageReq, params AddPageParams) (r *Page, _ error) {
return r, ht.ErrNotImplemented
}

View File

@@ -21,6 +21,12 @@ const (
FormatPDF
)
var AllFormats = []Format{
FormatHeaders,
FormatPDF,
FormatSingleFile,
}
type Status uint8
const (

View File

@@ -98,11 +98,7 @@ func FormatFromRest(format []openapi.Format) []entity.Format {
switch {
case len(format) == 0 || (len(format) == 1 && format[0] == openapi.FormatAll):
formats = []entity.Format{
entity.FormatHeaders,
entity.FormatPDF,
entity.FormatSingleFile,
}
formats = entity.AllFormats
default:
formats = make([]entity.Format, len(format))

View File

@@ -41,8 +41,26 @@ func (s *Service) GetPage(ctx context.Context, params openapi.GetPageParams) (op
return &restPage, nil
}
func (s *Service) AddPage(ctx context.Context, req openapi.OptAddPageReq) (*openapi.Page, error) {
page := entity.NewPage(req.Value.URL, req.Value.Description.Value, FormatFromRest(req.Value.Formats)...)
func (s *Service) AddPage(ctx context.Context, req openapi.OptAddPageReq, params openapi.AddPageParams) (*openapi.Page, error) {
url := params.URL.Or(req.Value.URL)
description := params.Description.Or(req.Value.Description.Value)
formats := req.Value.Formats
if len(formats) == 0 {
formats = params.Formats
}
if len(formats) == 0 {
formats = []openapi.Format{"all"}
}
switch {
case req.Value.URL != "":
url = req.Value.URL
case params.URL.IsSet():
url = params.URL.Value
}
page := entity.NewPage(url, description, FormatFromRest(formats)...)
page.Status = entity.StatusProcessing