feat: implement retrieve by hash function
This commit is contained in:
parent
e17aa7dc38
commit
8e03a1e087
19 changed files with 275 additions and 155 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -7,6 +7,7 @@
|
||||||
*.dll
|
*.dll
|
||||||
*.so
|
*.so
|
||||||
*.dylib
|
*.dylib
|
||||||
|
/short
|
||||||
|
|
||||||
# Test binary, built with `go test -c`
|
# Test binary, built with `go test -c`
|
||||||
*.test
|
*.test
|
||||||
|
|
20
go.mod
20
go.mod
|
@ -2,20 +2,32 @@ module github.com/babariviere/short
|
||||||
|
|
||||||
go 1.21.6
|
go 1.21.6
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/go-faster/errors v0.7.1
|
||||||
|
github.com/go-faster/jx v1.1.0
|
||||||
|
github.com/jackc/pgx/v5 v5.5.2
|
||||||
|
github.com/ogen-go/ogen v0.81.2
|
||||||
|
go.opentelemetry.io/otel v1.22.0
|
||||||
|
go.opentelemetry.io/otel/metric v1.22.0
|
||||||
|
go.opentelemetry.io/otel/trace v1.22.0
|
||||||
|
go.uber.org/multierr v1.11.0
|
||||||
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/dlclark/regexp2 v1.10.0 // indirect
|
github.com/dlclark/regexp2 v1.10.0 // indirect
|
||||||
github.com/fatih/color v1.16.0 // indirect
|
github.com/fatih/color v1.16.0 // indirect
|
||||||
github.com/ghodss/yaml v1.0.0 // indirect
|
github.com/ghodss/yaml v1.0.0 // indirect
|
||||||
github.com/go-faster/errors v0.7.1 // indirect
|
|
||||||
github.com/go-faster/jx v1.1.0 // indirect
|
|
||||||
github.com/go-faster/yaml v0.4.6 // indirect
|
github.com/go-faster/yaml v0.4.6 // indirect
|
||||||
|
github.com/go-logr/logr v1.4.1 // indirect
|
||||||
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
github.com/google/uuid v1.5.0 // indirect
|
github.com/google/uuid v1.5.0 // indirect
|
||||||
|
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||||
|
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
|
||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/ogen-go/ogen v0.81.2 // indirect
|
|
||||||
github.com/segmentio/asm v1.2.0 // indirect
|
github.com/segmentio/asm v1.2.0 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
|
||||||
go.uber.org/zap v1.26.0 // indirect
|
go.uber.org/zap v1.26.0 // indirect
|
||||||
|
golang.org/x/crypto v0.18.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20230725093048-515e97ebf090 // indirect
|
golang.org/x/exp v0.0.0-20230725093048-515e97ebf090 // indirect
|
||||||
golang.org/x/mod v0.14.0 // indirect
|
golang.org/x/mod v0.14.0 // indirect
|
||||||
golang.org/x/net v0.20.0 // indirect
|
golang.org/x/net v0.20.0 // indirect
|
||||||
|
|
25
go.sum
25
go.sum
|
@ -1,3 +1,4 @@
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/dlclark/regexp2 v1.10.0 h1:+/GIL799phkJqYW+3YbOd8LCcbHzT0Pbo8zl70MHsq0=
|
github.com/dlclark/regexp2 v1.10.0 h1:+/GIL799phkJqYW+3YbOd8LCcbHzT0Pbo8zl70MHsq0=
|
||||||
github.com/dlclark/regexp2 v1.10.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
github.com/dlclark/regexp2 v1.10.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||||
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||||
|
@ -10,8 +11,19 @@ github.com/go-faster/jx v1.1.0 h1:ZsW3wD+snOdmTDy9eIVgQdjUpXRRV4rqW8NS3t+20bg=
|
||||||
github.com/go-faster/jx v1.1.0/go.mod h1:vKDNikrKoyUmpzaJ0OkIkRQClNHFX/nF3dnTJZb3skg=
|
github.com/go-faster/jx v1.1.0/go.mod h1:vKDNikrKoyUmpzaJ0OkIkRQClNHFX/nF3dnTJZb3skg=
|
||||||
github.com/go-faster/yaml v0.4.6 h1:lOK/EhI04gCpPgPhgt0bChS6bvw7G3WwI8xxVe0sw9I=
|
github.com/go-faster/yaml v0.4.6 h1:lOK/EhI04gCpPgPhgt0bChS6bvw7G3WwI8xxVe0sw9I=
|
||||||
github.com/go-faster/yaml v0.4.6/go.mod h1:390dRIvV4zbnO7qC9FGo6YYutc+wyyUSHBgbXL52eXk=
|
github.com/go-faster/yaml v0.4.6/go.mod h1:390dRIvV4zbnO7qC9FGo6YYutc+wyyUSHBgbXL52eXk=
|
||||||
|
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
|
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
|
||||||
|
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
|
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||||
|
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||||
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
|
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
|
||||||
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||||
|
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||||
|
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
|
||||||
|
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||||
|
github.com/jackc/pgx/v5 v5.5.2 h1:iLlpgp4Cp/gC9Xuscl7lFL1PhhW+ZLtXZcrfCt4C3tA=
|
||||||
|
github.com/jackc/pgx/v5 v5.5.2/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
|
||||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
|
@ -19,12 +31,24 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE
|
||||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
github.com/ogen-go/ogen v0.81.2 h1:Dj5vSgC/1oqLE5t0T5qd4ARgsKTupJWsh3rW9/C7Lvk=
|
github.com/ogen-go/ogen v0.81.2 h1:Dj5vSgC/1oqLE5t0T5qd4ARgsKTupJWsh3rW9/C7Lvk=
|
||||||
github.com/ogen-go/ogen v0.81.2/go.mod h1:10Ch7SIzBMSLB8TVEt8KclMKkRyJ5qCh4Cfs0pdeoh8=
|
github.com/ogen-go/ogen v0.81.2/go.mod h1:10Ch7SIzBMSLB8TVEt8KclMKkRyJ5qCh4Cfs0pdeoh8=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
|
github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
|
||||||
github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
|
github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
go.opentelemetry.io/otel v1.22.0 h1:xS7Ku+7yTFvDfDraDIJVpw7XPyuHlB9MCiqqX5mcJ6Y=
|
||||||
|
go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI=
|
||||||
|
go.opentelemetry.io/otel/metric v1.22.0 h1:lypMQnGyJYeuYPhOM/bgjbFM6WE44W1/T45er4d8Hhg=
|
||||||
|
go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY=
|
||||||
|
go.opentelemetry.io/otel/trace v1.22.0 h1:Hg6pPujv0XG9QaVbGOBVHunyuLcCC3jN7WEhPx83XD0=
|
||||||
|
go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo=
|
||||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||||
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
|
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
|
||||||
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
|
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
|
||||||
|
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
|
||||||
|
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||||
golang.org/x/exp v0.0.0-20230725093048-515e97ebf090 h1:Di6/M8l0O2lCLc6VVRWhgCiApHV8MnQurBnFSHsQtNY=
|
golang.org/x/exp v0.0.0-20230725093048-515e97ebf090 h1:Di6/M8l0O2lCLc6VVRWhgCiApHV8MnQurBnFSHsQtNY=
|
||||||
golang.org/x/exp v0.0.0-20230725093048-515e97ebf090/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
|
golang.org/x/exp v0.0.0-20230725093048-515e97ebf090/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
|
||||||
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
|
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
|
||||||
|
@ -44,3 +68,4 @@ golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|
38
internal/api/handler.go
Normal file
38
internal/api/handler.go
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/babariviere/short/internal/db"
|
||||||
|
"github.com/babariviere/short/internal/oas"
|
||||||
|
"github.com/jackc/pgx/v5"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ oas.Handler = (*handler)(nil)
|
||||||
|
|
||||||
|
type handler struct {
|
||||||
|
oas.UnimplementedHandler
|
||||||
|
queries *db.Queries
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHandler(queries *db.Queries) *handler {
|
||||||
|
return &handler{
|
||||||
|
queries: queries,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *handler) RedirectLongURL(ctx context.Context, params oas.RedirectLongURLParams) (oas.RedirectLongURLRes, error) {
|
||||||
|
res, err := h.queries.GetURLByHash(ctx, params.Hash)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, pgx.ErrNoRows) {
|
||||||
|
return &oas.RedirectLongURLNotFound{}, nil
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("unable to fetch URL by hash: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &oas.RedirectLongURLTemporaryRedirect{
|
||||||
|
Location: oas.NewOptString(res.LongUrl),
|
||||||
|
}, nil
|
||||||
|
}
|
|
@ -17,21 +17,24 @@ import (
|
||||||
|
|
||||||
"github.com/ogen-go/ogen/conv"
|
"github.com/ogen-go/ogen/conv"
|
||||||
ht "github.com/ogen-go/ogen/http"
|
ht "github.com/ogen-go/ogen/http"
|
||||||
|
"github.com/ogen-go/ogen/otelogen"
|
||||||
"github.com/ogen-go/ogen/uri"
|
"github.com/ogen-go/ogen/uri"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Invoker invokes operations described by OpenAPI v3 specification.
|
// Invoker invokes operations described by OpenAPI v3 specification.
|
||||||
type Invoker interface {
|
type Invoker interface {
|
||||||
// CreatePost invokes POST /create operation.
|
// CreateShortURL invokes createShortURL operation.
|
||||||
|
//
|
||||||
|
// Create a shorten URL.
|
||||||
//
|
//
|
||||||
// POST /create
|
// POST /create
|
||||||
CreatePost(ctx context.Context, request *CreatePostReq) (CreatePostRes, error)
|
CreateShortURL(ctx context.Context, request *CreateShortURLReq) (CreateShortURLRes, error)
|
||||||
// HashGet invokes GET /{hash} operation.
|
// RedirectLongURL invokes redirectLongURL operation.
|
||||||
//
|
//
|
||||||
// Redirect client to long URL.
|
// Redirect client to long URL.
|
||||||
//
|
//
|
||||||
// GET /{hash}
|
// GET /{hash}
|
||||||
HashGet(ctx context.Context, params HashGetParams) (HashGetRes, error)
|
RedirectLongURL(ctx context.Context, params RedirectLongURLParams) (RedirectLongURLRes, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Client implements OAS client.
|
// Client implements OAS client.
|
||||||
|
@ -82,16 +85,19 @@ func (c *Client) requestURL(ctx context.Context) *url.URL {
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreatePost invokes POST /create operation.
|
// CreateShortURL invokes createShortURL operation.
|
||||||
|
//
|
||||||
|
// Create a shorten URL.
|
||||||
//
|
//
|
||||||
// POST /create
|
// POST /create
|
||||||
func (c *Client) CreatePost(ctx context.Context, request *CreatePostReq) (CreatePostRes, error) {
|
func (c *Client) CreateShortURL(ctx context.Context, request *CreateShortURLReq) (CreateShortURLRes, error) {
|
||||||
res, err := c.sendCreatePost(ctx, request)
|
res, err := c.sendCreateShortURL(ctx, request)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) sendCreatePost(ctx context.Context, request *CreatePostReq) (res CreatePostRes, err error) {
|
func (c *Client) sendCreateShortURL(ctx context.Context, request *CreateShortURLReq) (res CreateShortURLRes, err error) {
|
||||||
otelAttrs := []attribute.KeyValue{
|
otelAttrs := []attribute.KeyValue{
|
||||||
|
otelogen.OperationID("createShortURL"),
|
||||||
semconv.HTTPMethodKey.String("POST"),
|
semconv.HTTPMethodKey.String("POST"),
|
||||||
semconv.HTTPRouteKey.String("/create"),
|
semconv.HTTPRouteKey.String("/create"),
|
||||||
}
|
}
|
||||||
|
@ -108,7 +114,7 @@ func (c *Client) sendCreatePost(ctx context.Context, request *CreatePostReq) (re
|
||||||
c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...))
|
c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...))
|
||||||
|
|
||||||
// Start a span for this request.
|
// Start a span for this request.
|
||||||
ctx, span := c.cfg.Tracer.Start(ctx, "CreatePost",
|
ctx, span := c.cfg.Tracer.Start(ctx, "CreateShortURL",
|
||||||
trace.WithAttributes(otelAttrs...),
|
trace.WithAttributes(otelAttrs...),
|
||||||
clientSpanKind,
|
clientSpanKind,
|
||||||
)
|
)
|
||||||
|
@ -134,7 +140,7 @@ func (c *Client) sendCreatePost(ctx context.Context, request *CreatePostReq) (re
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, errors.Wrap(err, "create request")
|
return res, errors.Wrap(err, "create request")
|
||||||
}
|
}
|
||||||
if err := encodeCreatePostRequest(request, r); err != nil {
|
if err := encodeCreateShortURLRequest(request, r); err != nil {
|
||||||
return res, errors.Wrap(err, "encode request")
|
return res, errors.Wrap(err, "encode request")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,7 +152,7 @@ func (c *Client) sendCreatePost(ctx context.Context, request *CreatePostReq) (re
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
stage = "DecodeResponse"
|
stage = "DecodeResponse"
|
||||||
result, err := decodeCreatePostResponse(resp)
|
result, err := decodeCreateShortURLResponse(resp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, errors.Wrap(err, "decode response")
|
return res, errors.Wrap(err, "decode response")
|
||||||
}
|
}
|
||||||
|
@ -154,18 +160,19 @@ func (c *Client) sendCreatePost(ctx context.Context, request *CreatePostReq) (re
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// HashGet invokes GET /{hash} operation.
|
// RedirectLongURL invokes redirectLongURL operation.
|
||||||
//
|
//
|
||||||
// Redirect client to long URL.
|
// Redirect client to long URL.
|
||||||
//
|
//
|
||||||
// GET /{hash}
|
// GET /{hash}
|
||||||
func (c *Client) HashGet(ctx context.Context, params HashGetParams) (HashGetRes, error) {
|
func (c *Client) RedirectLongURL(ctx context.Context, params RedirectLongURLParams) (RedirectLongURLRes, error) {
|
||||||
res, err := c.sendHashGet(ctx, params)
|
res, err := c.sendRedirectLongURL(ctx, params)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) sendHashGet(ctx context.Context, params HashGetParams) (res HashGetRes, err error) {
|
func (c *Client) sendRedirectLongURL(ctx context.Context, params RedirectLongURLParams) (res RedirectLongURLRes, err error) {
|
||||||
otelAttrs := []attribute.KeyValue{
|
otelAttrs := []attribute.KeyValue{
|
||||||
|
otelogen.OperationID("redirectLongURL"),
|
||||||
semconv.HTTPMethodKey.String("GET"),
|
semconv.HTTPMethodKey.String("GET"),
|
||||||
semconv.HTTPRouteKey.String("/{hash}"),
|
semconv.HTTPRouteKey.String("/{hash}"),
|
||||||
}
|
}
|
||||||
|
@ -182,7 +189,7 @@ func (c *Client) sendHashGet(ctx context.Context, params HashGetParams) (res Has
|
||||||
c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...))
|
c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...))
|
||||||
|
|
||||||
// Start a span for this request.
|
// Start a span for this request.
|
||||||
ctx, span := c.cfg.Tracer.Start(ctx, "HashGet",
|
ctx, span := c.cfg.Tracer.Start(ctx, "RedirectLongURL",
|
||||||
trace.WithAttributes(otelAttrs...),
|
trace.WithAttributes(otelAttrs...),
|
||||||
clientSpanKind,
|
clientSpanKind,
|
||||||
)
|
)
|
||||||
|
@ -235,7 +242,7 @@ func (c *Client) sendHashGet(ctx context.Context, params HashGetParams) (res Has
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
stage = "DecodeResponse"
|
stage = "DecodeResponse"
|
||||||
result, err := decodeHashGetResponse(resp)
|
result, err := decodeRedirectLongURLResponse(resp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, errors.Wrap(err, "decode response")
|
return res, errors.Wrap(err, "decode response")
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,19 +17,23 @@ import (
|
||||||
ht "github.com/ogen-go/ogen/http"
|
ht "github.com/ogen-go/ogen/http"
|
||||||
"github.com/ogen-go/ogen/middleware"
|
"github.com/ogen-go/ogen/middleware"
|
||||||
"github.com/ogen-go/ogen/ogenerrors"
|
"github.com/ogen-go/ogen/ogenerrors"
|
||||||
|
"github.com/ogen-go/ogen/otelogen"
|
||||||
)
|
)
|
||||||
|
|
||||||
// handleCreatePostRequest handles POST /create operation.
|
// handleCreateShortURLRequest handles createShortURL operation.
|
||||||
|
//
|
||||||
|
// Create a shorten URL.
|
||||||
//
|
//
|
||||||
// POST /create
|
// POST /create
|
||||||
func (s *Server) handleCreatePostRequest(args [0]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
|
func (s *Server) handleCreateShortURLRequest(args [0]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
|
||||||
otelAttrs := []attribute.KeyValue{
|
otelAttrs := []attribute.KeyValue{
|
||||||
|
otelogen.OperationID("createShortURL"),
|
||||||
semconv.HTTPMethodKey.String("POST"),
|
semconv.HTTPMethodKey.String("POST"),
|
||||||
semconv.HTTPRouteKey.String("/create"),
|
semconv.HTTPRouteKey.String("/create"),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start a span for this request.
|
// Start a span for this request.
|
||||||
ctx, span := s.cfg.Tracer.Start(r.Context(), "CreatePost",
|
ctx, span := s.cfg.Tracer.Start(r.Context(), "CreateShortURL",
|
||||||
trace.WithAttributes(otelAttrs...),
|
trace.WithAttributes(otelAttrs...),
|
||||||
serverSpanKind,
|
serverSpanKind,
|
||||||
)
|
)
|
||||||
|
@ -54,11 +58,11 @@ func (s *Server) handleCreatePostRequest(args [0]string, argsEscaped bool, w htt
|
||||||
}
|
}
|
||||||
err error
|
err error
|
||||||
opErrContext = ogenerrors.OperationContext{
|
opErrContext = ogenerrors.OperationContext{
|
||||||
Name: "CreatePost",
|
Name: "CreateShortURL",
|
||||||
ID: "",
|
ID: "createShortURL",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
request, close, err := s.decodeCreatePostRequest(r)
|
request, close, err := s.decodeCreateShortURLRequest(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = &ogenerrors.DecodeRequestError{
|
err = &ogenerrors.DecodeRequestError{
|
||||||
OperationContext: opErrContext,
|
OperationContext: opErrContext,
|
||||||
|
@ -74,22 +78,22 @@ func (s *Server) handleCreatePostRequest(args [0]string, argsEscaped bool, w htt
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
var response CreatePostRes
|
var response CreateShortURLRes
|
||||||
if m := s.cfg.Middleware; m != nil {
|
if m := s.cfg.Middleware; m != nil {
|
||||||
mreq := middleware.Request{
|
mreq := middleware.Request{
|
||||||
Context: ctx,
|
Context: ctx,
|
||||||
OperationName: "CreatePost",
|
OperationName: "CreateShortURL",
|
||||||
OperationSummary: "",
|
OperationSummary: "",
|
||||||
OperationID: "",
|
OperationID: "createShortURL",
|
||||||
Body: request,
|
Body: request,
|
||||||
Params: middleware.Parameters{},
|
Params: middleware.Parameters{},
|
||||||
Raw: r,
|
Raw: r,
|
||||||
}
|
}
|
||||||
|
|
||||||
type (
|
type (
|
||||||
Request = *CreatePostReq
|
Request = *CreateShortURLReq
|
||||||
Params = struct{}
|
Params = struct{}
|
||||||
Response = CreatePostRes
|
Response = CreateShortURLRes
|
||||||
)
|
)
|
||||||
response, err = middleware.HookMiddleware[
|
response, err = middleware.HookMiddleware[
|
||||||
Request,
|
Request,
|
||||||
|
@ -100,12 +104,12 @@ func (s *Server) handleCreatePostRequest(args [0]string, argsEscaped bool, w htt
|
||||||
mreq,
|
mreq,
|
||||||
nil,
|
nil,
|
||||||
func(ctx context.Context, request Request, params Params) (response Response, err error) {
|
func(ctx context.Context, request Request, params Params) (response Response, err error) {
|
||||||
response, err = s.h.CreatePost(ctx, request)
|
response, err = s.h.CreateShortURL(ctx, request)
|
||||||
return response, err
|
return response, err
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
response, err = s.h.CreatePost(ctx, request)
|
response, err = s.h.CreateShortURL(ctx, request)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
recordError("Internal", err)
|
recordError("Internal", err)
|
||||||
|
@ -113,7 +117,7 @@ func (s *Server) handleCreatePostRequest(args [0]string, argsEscaped bool, w htt
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := encodeCreatePostResponse(response, w, span); err != nil {
|
if err := encodeCreateShortURLResponse(response, w, span); err != nil {
|
||||||
recordError("EncodeResponse", err)
|
recordError("EncodeResponse", err)
|
||||||
if !errors.Is(err, ht.ErrInternalServerErrorResponse) {
|
if !errors.Is(err, ht.ErrInternalServerErrorResponse) {
|
||||||
s.cfg.ErrorHandler(ctx, w, r, err)
|
s.cfg.ErrorHandler(ctx, w, r, err)
|
||||||
|
@ -122,19 +126,20 @@ func (s *Server) handleCreatePostRequest(args [0]string, argsEscaped bool, w htt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleHashGetRequest handles GET /{hash} operation.
|
// handleRedirectLongURLRequest handles redirectLongURL operation.
|
||||||
//
|
//
|
||||||
// Redirect client to long URL.
|
// Redirect client to long URL.
|
||||||
//
|
//
|
||||||
// GET /{hash}
|
// GET /{hash}
|
||||||
func (s *Server) handleHashGetRequest(args [1]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
|
func (s *Server) handleRedirectLongURLRequest(args [1]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
|
||||||
otelAttrs := []attribute.KeyValue{
|
otelAttrs := []attribute.KeyValue{
|
||||||
|
otelogen.OperationID("redirectLongURL"),
|
||||||
semconv.HTTPMethodKey.String("GET"),
|
semconv.HTTPMethodKey.String("GET"),
|
||||||
semconv.HTTPRouteKey.String("/{hash}"),
|
semconv.HTTPRouteKey.String("/{hash}"),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start a span for this request.
|
// Start a span for this request.
|
||||||
ctx, span := s.cfg.Tracer.Start(r.Context(), "HashGet",
|
ctx, span := s.cfg.Tracer.Start(r.Context(), "RedirectLongURL",
|
||||||
trace.WithAttributes(otelAttrs...),
|
trace.WithAttributes(otelAttrs...),
|
||||||
serverSpanKind,
|
serverSpanKind,
|
||||||
)
|
)
|
||||||
|
@ -159,11 +164,11 @@ func (s *Server) handleHashGetRequest(args [1]string, argsEscaped bool, w http.R
|
||||||
}
|
}
|
||||||
err error
|
err error
|
||||||
opErrContext = ogenerrors.OperationContext{
|
opErrContext = ogenerrors.OperationContext{
|
||||||
Name: "HashGet",
|
Name: "RedirectLongURL",
|
||||||
ID: "",
|
ID: "redirectLongURL",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
params, err := decodeHashGetParams(args, argsEscaped, r)
|
params, err := decodeRedirectLongURLParams(args, argsEscaped, r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = &ogenerrors.DecodeParamsError{
|
err = &ogenerrors.DecodeParamsError{
|
||||||
OperationContext: opErrContext,
|
OperationContext: opErrContext,
|
||||||
|
@ -174,13 +179,13 @@ func (s *Server) handleHashGetRequest(args [1]string, argsEscaped bool, w http.R
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var response HashGetRes
|
var response RedirectLongURLRes
|
||||||
if m := s.cfg.Middleware; m != nil {
|
if m := s.cfg.Middleware; m != nil {
|
||||||
mreq := middleware.Request{
|
mreq := middleware.Request{
|
||||||
Context: ctx,
|
Context: ctx,
|
||||||
OperationName: "HashGet",
|
OperationName: "RedirectLongURL",
|
||||||
OperationSummary: "",
|
OperationSummary: "",
|
||||||
OperationID: "",
|
OperationID: "redirectLongURL",
|
||||||
Body: nil,
|
Body: nil,
|
||||||
Params: middleware.Parameters{
|
Params: middleware.Parameters{
|
||||||
{
|
{
|
||||||
|
@ -193,8 +198,8 @@ func (s *Server) handleHashGetRequest(args [1]string, argsEscaped bool, w http.R
|
||||||
|
|
||||||
type (
|
type (
|
||||||
Request = struct{}
|
Request = struct{}
|
||||||
Params = HashGetParams
|
Params = RedirectLongURLParams
|
||||||
Response = HashGetRes
|
Response = RedirectLongURLRes
|
||||||
)
|
)
|
||||||
response, err = middleware.HookMiddleware[
|
response, err = middleware.HookMiddleware[
|
||||||
Request,
|
Request,
|
||||||
|
@ -203,14 +208,14 @@ func (s *Server) handleHashGetRequest(args [1]string, argsEscaped bool, w http.R
|
||||||
](
|
](
|
||||||
m,
|
m,
|
||||||
mreq,
|
mreq,
|
||||||
unpackHashGetParams,
|
unpackRedirectLongURLParams,
|
||||||
func(ctx context.Context, request Request, params Params) (response Response, err error) {
|
func(ctx context.Context, request Request, params Params) (response Response, err error) {
|
||||||
response, err = s.h.HashGet(ctx, params)
|
response, err = s.h.RedirectLongURL(ctx, params)
|
||||||
return response, err
|
return response, err
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
response, err = s.h.HashGet(ctx, params)
|
response, err = s.h.RedirectLongURL(ctx, params)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
recordError("Internal", err)
|
recordError("Internal", err)
|
||||||
|
@ -218,7 +223,7 @@ func (s *Server) handleHashGetRequest(args [1]string, argsEscaped bool, w http.R
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := encodeHashGetResponse(response, w, span); err != nil {
|
if err := encodeRedirectLongURLResponse(response, w, span); err != nil {
|
||||||
recordError("EncodeResponse", err)
|
recordError("EncodeResponse", err)
|
||||||
if !errors.Is(err, ht.ErrInternalServerErrorResponse) {
|
if !errors.Is(err, ht.ErrInternalServerErrorResponse) {
|
||||||
s.cfg.ErrorHandler(ctx, w, r, err)
|
s.cfg.ErrorHandler(ctx, w, r, err)
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
// Code generated by ogen, DO NOT EDIT.
|
// Code generated by ogen, DO NOT EDIT.
|
||||||
package oas
|
package oas
|
||||||
|
|
||||||
type CreatePostRes interface {
|
type CreateShortURLRes interface {
|
||||||
createPostRes()
|
createShortURLRes()
|
||||||
}
|
}
|
||||||
|
|
||||||
type HashGetRes interface {
|
type RedirectLongURLRes interface {
|
||||||
hashGetRes()
|
redirectLongURLRes()
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,14 +13,14 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Encode implements json.Marshaler.
|
// Encode implements json.Marshaler.
|
||||||
func (s *CreatePostBadRequest) Encode(e *jx.Encoder) {
|
func (s *CreateShortURLBadRequest) Encode(e *jx.Encoder) {
|
||||||
e.ObjStart()
|
e.ObjStart()
|
||||||
s.encodeFields(e)
|
s.encodeFields(e)
|
||||||
e.ObjEnd()
|
e.ObjEnd()
|
||||||
}
|
}
|
||||||
|
|
||||||
// encodeFields encodes fields.
|
// encodeFields encodes fields.
|
||||||
func (s *CreatePostBadRequest) encodeFields(e *jx.Encoder) {
|
func (s *CreateShortURLBadRequest) encodeFields(e *jx.Encoder) {
|
||||||
{
|
{
|
||||||
if s.Message.Set {
|
if s.Message.Set {
|
||||||
e.FieldStart("message")
|
e.FieldStart("message")
|
||||||
|
@ -29,14 +29,14 @@ func (s *CreatePostBadRequest) encodeFields(e *jx.Encoder) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var jsonFieldsNameOfCreatePostBadRequest = [1]string{
|
var jsonFieldsNameOfCreateShortURLBadRequest = [1]string{
|
||||||
0: "message",
|
0: "message",
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decode decodes CreatePostBadRequest from json.
|
// Decode decodes CreateShortURLBadRequest from json.
|
||||||
func (s *CreatePostBadRequest) Decode(d *jx.Decoder) error {
|
func (s *CreateShortURLBadRequest) Decode(d *jx.Decoder) error {
|
||||||
if s == nil {
|
if s == nil {
|
||||||
return errors.New("invalid: unable to decode CreatePostBadRequest to nil")
|
return errors.New("invalid: unable to decode CreateShortURLBadRequest to nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := d.ObjBytes(func(d *jx.Decoder, k []byte) error {
|
if err := d.ObjBytes(func(d *jx.Decoder, k []byte) error {
|
||||||
|
@ -56,34 +56,34 @@ func (s *CreatePostBadRequest) Decode(d *jx.Decoder) error {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return errors.Wrap(err, "decode CreatePostBadRequest")
|
return errors.Wrap(err, "decode CreateShortURLBadRequest")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalJSON implements stdjson.Marshaler.
|
// MarshalJSON implements stdjson.Marshaler.
|
||||||
func (s *CreatePostBadRequest) MarshalJSON() ([]byte, error) {
|
func (s *CreateShortURLBadRequest) MarshalJSON() ([]byte, error) {
|
||||||
e := jx.Encoder{}
|
e := jx.Encoder{}
|
||||||
s.Encode(&e)
|
s.Encode(&e)
|
||||||
return e.Bytes(), nil
|
return e.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON implements stdjson.Unmarshaler.
|
// UnmarshalJSON implements stdjson.Unmarshaler.
|
||||||
func (s *CreatePostBadRequest) UnmarshalJSON(data []byte) error {
|
func (s *CreateShortURLBadRequest) UnmarshalJSON(data []byte) error {
|
||||||
d := jx.DecodeBytes(data)
|
d := jx.DecodeBytes(data)
|
||||||
return s.Decode(d)
|
return s.Decode(d)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encode implements json.Marshaler.
|
// Encode implements json.Marshaler.
|
||||||
func (s *CreatePostCreated) Encode(e *jx.Encoder) {
|
func (s *CreateShortURLCreated) Encode(e *jx.Encoder) {
|
||||||
e.ObjStart()
|
e.ObjStart()
|
||||||
s.encodeFields(e)
|
s.encodeFields(e)
|
||||||
e.ObjEnd()
|
e.ObjEnd()
|
||||||
}
|
}
|
||||||
|
|
||||||
// encodeFields encodes fields.
|
// encodeFields encodes fields.
|
||||||
func (s *CreatePostCreated) encodeFields(e *jx.Encoder) {
|
func (s *CreateShortURLCreated) encodeFields(e *jx.Encoder) {
|
||||||
{
|
{
|
||||||
if s.Shorten.Set {
|
if s.Shorten.Set {
|
||||||
e.FieldStart("shorten")
|
e.FieldStart("shorten")
|
||||||
|
@ -92,14 +92,14 @@ func (s *CreatePostCreated) encodeFields(e *jx.Encoder) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var jsonFieldsNameOfCreatePostCreated = [1]string{
|
var jsonFieldsNameOfCreateShortURLCreated = [1]string{
|
||||||
0: "shorten",
|
0: "shorten",
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decode decodes CreatePostCreated from json.
|
// Decode decodes CreateShortURLCreated from json.
|
||||||
func (s *CreatePostCreated) Decode(d *jx.Decoder) error {
|
func (s *CreateShortURLCreated) Decode(d *jx.Decoder) error {
|
||||||
if s == nil {
|
if s == nil {
|
||||||
return errors.New("invalid: unable to decode CreatePostCreated to nil")
|
return errors.New("invalid: unable to decode CreateShortURLCreated to nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := d.ObjBytes(func(d *jx.Decoder, k []byte) error {
|
if err := d.ObjBytes(func(d *jx.Decoder, k []byte) error {
|
||||||
|
@ -119,48 +119,48 @@ func (s *CreatePostCreated) Decode(d *jx.Decoder) error {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return errors.Wrap(err, "decode CreatePostCreated")
|
return errors.Wrap(err, "decode CreateShortURLCreated")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalJSON implements stdjson.Marshaler.
|
// MarshalJSON implements stdjson.Marshaler.
|
||||||
func (s *CreatePostCreated) MarshalJSON() ([]byte, error) {
|
func (s *CreateShortURLCreated) MarshalJSON() ([]byte, error) {
|
||||||
e := jx.Encoder{}
|
e := jx.Encoder{}
|
||||||
s.Encode(&e)
|
s.Encode(&e)
|
||||||
return e.Bytes(), nil
|
return e.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON implements stdjson.Unmarshaler.
|
// UnmarshalJSON implements stdjson.Unmarshaler.
|
||||||
func (s *CreatePostCreated) UnmarshalJSON(data []byte) error {
|
func (s *CreateShortURLCreated) UnmarshalJSON(data []byte) error {
|
||||||
d := jx.DecodeBytes(data)
|
d := jx.DecodeBytes(data)
|
||||||
return s.Decode(d)
|
return s.Decode(d)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encode implements json.Marshaler.
|
// Encode implements json.Marshaler.
|
||||||
func (s *CreatePostReq) Encode(e *jx.Encoder) {
|
func (s *CreateShortURLReq) Encode(e *jx.Encoder) {
|
||||||
e.ObjStart()
|
e.ObjStart()
|
||||||
s.encodeFields(e)
|
s.encodeFields(e)
|
||||||
e.ObjEnd()
|
e.ObjEnd()
|
||||||
}
|
}
|
||||||
|
|
||||||
// encodeFields encodes fields.
|
// encodeFields encodes fields.
|
||||||
func (s *CreatePostReq) encodeFields(e *jx.Encoder) {
|
func (s *CreateShortURLReq) encodeFields(e *jx.Encoder) {
|
||||||
{
|
{
|
||||||
e.FieldStart("url")
|
e.FieldStart("url")
|
||||||
e.Str(s.URL)
|
e.Str(s.URL)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var jsonFieldsNameOfCreatePostReq = [1]string{
|
var jsonFieldsNameOfCreateShortURLReq = [1]string{
|
||||||
0: "url",
|
0: "url",
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decode decodes CreatePostReq from json.
|
// Decode decodes CreateShortURLReq from json.
|
||||||
func (s *CreatePostReq) Decode(d *jx.Decoder) error {
|
func (s *CreateShortURLReq) Decode(d *jx.Decoder) error {
|
||||||
if s == nil {
|
if s == nil {
|
||||||
return errors.New("invalid: unable to decode CreatePostReq to nil")
|
return errors.New("invalid: unable to decode CreateShortURLReq to nil")
|
||||||
}
|
}
|
||||||
var requiredBitSet [1]uint8
|
var requiredBitSet [1]uint8
|
||||||
|
|
||||||
|
@ -183,7 +183,7 @@ func (s *CreatePostReq) Decode(d *jx.Decoder) error {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return errors.Wrap(err, "decode CreatePostReq")
|
return errors.Wrap(err, "decode CreateShortURLReq")
|
||||||
}
|
}
|
||||||
// Validate required fields.
|
// Validate required fields.
|
||||||
var failures []validate.FieldError
|
var failures []validate.FieldError
|
||||||
|
@ -200,8 +200,8 @@ func (s *CreatePostReq) Decode(d *jx.Decoder) error {
|
||||||
bitIdx := bits.TrailingZeros8(result)
|
bitIdx := bits.TrailingZeros8(result)
|
||||||
fieldIdx := i*8 + bitIdx
|
fieldIdx := i*8 + bitIdx
|
||||||
var name string
|
var name string
|
||||||
if fieldIdx < len(jsonFieldsNameOfCreatePostReq) {
|
if fieldIdx < len(jsonFieldsNameOfCreateShortURLReq) {
|
||||||
name = jsonFieldsNameOfCreatePostReq[fieldIdx]
|
name = jsonFieldsNameOfCreateShortURLReq[fieldIdx]
|
||||||
} else {
|
} else {
|
||||||
name = strconv.Itoa(fieldIdx)
|
name = strconv.Itoa(fieldIdx)
|
||||||
}
|
}
|
||||||
|
@ -222,14 +222,14 @@ func (s *CreatePostReq) Decode(d *jx.Decoder) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalJSON implements stdjson.Marshaler.
|
// MarshalJSON implements stdjson.Marshaler.
|
||||||
func (s *CreatePostReq) MarshalJSON() ([]byte, error) {
|
func (s *CreateShortURLReq) MarshalJSON() ([]byte, error) {
|
||||||
e := jx.Encoder{}
|
e := jx.Encoder{}
|
||||||
s.Encode(&e)
|
s.Encode(&e)
|
||||||
return e.Bytes(), nil
|
return e.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON implements stdjson.Unmarshaler.
|
// UnmarshalJSON implements stdjson.Unmarshaler.
|
||||||
func (s *CreatePostReq) UnmarshalJSON(data []byte) error {
|
func (s *CreateShortURLReq) UnmarshalJSON(data []byte) error {
|
||||||
d := jx.DecodeBytes(data)
|
d := jx.DecodeBytes(data)
|
||||||
return s.Decode(d)
|
return s.Decode(d)
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,13 +15,13 @@ import (
|
||||||
"github.com/ogen-go/ogen/validate"
|
"github.com/ogen-go/ogen/validate"
|
||||||
)
|
)
|
||||||
|
|
||||||
// HashGetParams is parameters of GET /{hash} operation.
|
// RedirectLongURLParams is parameters of redirectLongURL operation.
|
||||||
type HashGetParams struct {
|
type RedirectLongURLParams struct {
|
||||||
// Hash of shorten URL.
|
// Hash of shorten URL.
|
||||||
Hash string
|
Hash string
|
||||||
}
|
}
|
||||||
|
|
||||||
func unpackHashGetParams(packed middleware.Parameters) (params HashGetParams) {
|
func unpackRedirectLongURLParams(packed middleware.Parameters) (params RedirectLongURLParams) {
|
||||||
{
|
{
|
||||||
key := middleware.ParameterKey{
|
key := middleware.ParameterKey{
|
||||||
Name: "hash",
|
Name: "hash",
|
||||||
|
@ -32,7 +32,7 @@ func unpackHashGetParams(packed middleware.Parameters) (params HashGetParams) {
|
||||||
return params
|
return params
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeHashGetParams(args [1]string, argsEscaped bool, r *http.Request) (params HashGetParams, _ error) {
|
func decodeRedirectLongURLParams(args [1]string, argsEscaped bool, r *http.Request) (params RedirectLongURLParams, _ error) {
|
||||||
// Decode path: hash.
|
// Decode path: hash.
|
||||||
if err := func() error {
|
if err := func() error {
|
||||||
param := args[0]
|
param := args[0]
|
||||||
|
|
|
@ -15,8 +15,8 @@ import (
|
||||||
"github.com/ogen-go/ogen/validate"
|
"github.com/ogen-go/ogen/validate"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Server) decodeCreatePostRequest(r *http.Request) (
|
func (s *Server) decodeCreateShortURLRequest(r *http.Request) (
|
||||||
req *CreatePostReq,
|
req *CreateShortURLReq,
|
||||||
close func() error,
|
close func() error,
|
||||||
rerr error,
|
rerr error,
|
||||||
) {
|
) {
|
||||||
|
@ -55,7 +55,7 @@ func (s *Server) decodeCreatePostRequest(r *http.Request) (
|
||||||
|
|
||||||
d := jx.DecodeBytes(buf)
|
d := jx.DecodeBytes(buf)
|
||||||
|
|
||||||
var request CreatePostReq
|
var request CreateShortURLReq
|
||||||
if err := func() error {
|
if err := func() error {
|
||||||
if err := request.Decode(d); err != nil {
|
if err := request.Decode(d); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -11,8 +11,8 @@ import (
|
||||||
ht "github.com/ogen-go/ogen/http"
|
ht "github.com/ogen-go/ogen/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
func encodeCreatePostRequest(
|
func encodeCreateShortURLRequest(
|
||||||
req *CreatePostReq,
|
req *CreateShortURLReq,
|
||||||
r *http.Request,
|
r *http.Request,
|
||||||
) error {
|
) error {
|
||||||
const contentType = "application/json"
|
const contentType = "application/json"
|
||||||
|
|
|
@ -16,7 +16,7 @@ import (
|
||||||
"github.com/ogen-go/ogen/validate"
|
"github.com/ogen-go/ogen/validate"
|
||||||
)
|
)
|
||||||
|
|
||||||
func decodeCreatePostResponse(resp *http.Response) (res CreatePostRes, _ error) {
|
func decodeCreateShortURLResponse(resp *http.Response) (res CreateShortURLRes, _ error) {
|
||||||
switch resp.StatusCode {
|
switch resp.StatusCode {
|
||||||
case 201:
|
case 201:
|
||||||
// Code 201.
|
// Code 201.
|
||||||
|
@ -32,7 +32,7 @@ func decodeCreatePostResponse(resp *http.Response) (res CreatePostRes, _ error)
|
||||||
}
|
}
|
||||||
d := jx.DecodeBytes(buf)
|
d := jx.DecodeBytes(buf)
|
||||||
|
|
||||||
var response CreatePostCreated
|
var response CreateShortURLCreated
|
||||||
if err := func() error {
|
if err := func() error {
|
||||||
if err := response.Decode(d); err != nil {
|
if err := response.Decode(d); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -67,7 +67,7 @@ func decodeCreatePostResponse(resp *http.Response) (res CreatePostRes, _ error)
|
||||||
}
|
}
|
||||||
d := jx.DecodeBytes(buf)
|
d := jx.DecodeBytes(buf)
|
||||||
|
|
||||||
var response CreatePostBadRequest
|
var response CreateShortURLBadRequest
|
||||||
if err := func() error {
|
if err := func() error {
|
||||||
if err := response.Decode(d); err != nil {
|
if err := response.Decode(d); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -92,11 +92,11 @@ func decodeCreatePostResponse(resp *http.Response) (res CreatePostRes, _ error)
|
||||||
return res, validate.UnexpectedStatusCode(resp.StatusCode)
|
return res, validate.UnexpectedStatusCode(resp.StatusCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeHashGetResponse(resp *http.Response) (res HashGetRes, _ error) {
|
func decodeRedirectLongURLResponse(resp *http.Response) (res RedirectLongURLRes, _ error) {
|
||||||
switch resp.StatusCode {
|
switch resp.StatusCode {
|
||||||
case 307:
|
case 307:
|
||||||
// Code 307.
|
// Code 307.
|
||||||
var wrapper HashGetTemporaryRedirect
|
var wrapper RedirectLongURLTemporaryRedirect
|
||||||
h := uri.NewHeaderDecoder(resp.Header)
|
h := uri.NewHeaderDecoder(resp.Header)
|
||||||
// Parse "Location" header.
|
// Parse "Location" header.
|
||||||
{
|
{
|
||||||
|
@ -138,7 +138,7 @@ func decodeHashGetResponse(resp *http.Response) (res HashGetRes, _ error) {
|
||||||
return &wrapper, nil
|
return &wrapper, nil
|
||||||
case 404:
|
case 404:
|
||||||
// Code 404.
|
// Code 404.
|
||||||
return &HashGetNotFound{}, nil
|
return &RedirectLongURLNotFound{}, nil
|
||||||
}
|
}
|
||||||
return res, validate.UnexpectedStatusCode(resp.StatusCode)
|
return res, validate.UnexpectedStatusCode(resp.StatusCode)
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,9 +14,9 @@ import (
|
||||||
"github.com/ogen-go/ogen/uri"
|
"github.com/ogen-go/ogen/uri"
|
||||||
)
|
)
|
||||||
|
|
||||||
func encodeCreatePostResponse(response CreatePostRes, w http.ResponseWriter, span trace.Span) error {
|
func encodeCreateShortURLResponse(response CreateShortURLRes, w http.ResponseWriter, span trace.Span) error {
|
||||||
switch response := response.(type) {
|
switch response := response.(type) {
|
||||||
case *CreatePostCreated:
|
case *CreateShortURLCreated:
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
w.WriteHeader(201)
|
w.WriteHeader(201)
|
||||||
span.SetStatus(codes.Ok, http.StatusText(201))
|
span.SetStatus(codes.Ok, http.StatusText(201))
|
||||||
|
@ -29,7 +29,7 @@ func encodeCreatePostResponse(response CreatePostRes, w http.ResponseWriter, spa
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
case *CreatePostBadRequest:
|
case *CreateShortURLBadRequest:
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
w.WriteHeader(400)
|
w.WriteHeader(400)
|
||||||
span.SetStatus(codes.Error, http.StatusText(400))
|
span.SetStatus(codes.Error, http.StatusText(400))
|
||||||
|
@ -47,9 +47,9 @@ func encodeCreatePostResponse(response CreatePostRes, w http.ResponseWriter, spa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func encodeHashGetResponse(response HashGetRes, w http.ResponseWriter, span trace.Span) error {
|
func encodeRedirectLongURLResponse(response RedirectLongURLRes, w http.ResponseWriter, span trace.Span) error {
|
||||||
switch response := response.(type) {
|
switch response := response.(type) {
|
||||||
case *HashGetTemporaryRedirect:
|
case *RedirectLongURLTemporaryRedirect:
|
||||||
// Encoding response headers.
|
// Encoding response headers.
|
||||||
{
|
{
|
||||||
h := uri.NewHeaderEncoder(w.Header())
|
h := uri.NewHeaderEncoder(w.Header())
|
||||||
|
@ -74,7 +74,7 @@ func encodeHashGetResponse(response HashGetRes, w http.ResponseWriter, span trac
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
case *HashGetNotFound:
|
case *RedirectLongURLNotFound:
|
||||||
w.WriteHeader(404)
|
w.WriteHeader(404)
|
||||||
span.SetStatus(codes.Error, http.StatusText(404))
|
span.SetStatus(codes.Error, http.StatusText(404))
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
// Leaf node.
|
// Leaf node.
|
||||||
switch r.Method {
|
switch r.Method {
|
||||||
case "POST":
|
case "POST":
|
||||||
s.handleCreatePostRequest([0]string{}, elemIsEscaped, w, r)
|
s.handleCreateShortURLRequest([0]string{}, elemIsEscaped, w, r)
|
||||||
default:
|
default:
|
||||||
s.notAllowed(w, r, "POST")
|
s.notAllowed(w, r, "POST")
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
// Leaf node.
|
// Leaf node.
|
||||||
switch r.Method {
|
switch r.Method {
|
||||||
case "GET":
|
case "GET":
|
||||||
s.handleHashGetRequest([1]string{
|
s.handleRedirectLongURLRequest([1]string{
|
||||||
args[0],
|
args[0],
|
||||||
}, elemIsEscaped, w, r)
|
}, elemIsEscaped, w, r)
|
||||||
default:
|
default:
|
||||||
|
@ -206,10 +206,10 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
||||||
if len(elem) == 0 {
|
if len(elem) == 0 {
|
||||||
switch method {
|
switch method {
|
||||||
case "POST":
|
case "POST":
|
||||||
// Leaf: CreatePost
|
// Leaf: CreateShortURL
|
||||||
r.name = "CreatePost"
|
r.name = "CreateShortURL"
|
||||||
r.summary = ""
|
r.summary = ""
|
||||||
r.operationID = ""
|
r.operationID = "createShortURL"
|
||||||
r.pathPattern = "/create"
|
r.pathPattern = "/create"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 0
|
r.count = 0
|
||||||
|
@ -229,10 +229,10 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
|
||||||
if len(elem) == 0 {
|
if len(elem) == 0 {
|
||||||
switch method {
|
switch method {
|
||||||
case "GET":
|
case "GET":
|
||||||
// Leaf: HashGet
|
// Leaf: RedirectLongURL
|
||||||
r.name = "HashGet"
|
r.name = "RedirectLongURL"
|
||||||
r.summary = ""
|
r.summary = ""
|
||||||
r.operationID = ""
|
r.operationID = "redirectLongURL"
|
||||||
r.pathPattern = "/{hash}"
|
r.pathPattern = "/{hash}"
|
||||||
r.args = args
|
r.args = args
|
||||||
r.count = 1
|
r.count = 1
|
||||||
|
|
|
@ -2,76 +2,54 @@
|
||||||
|
|
||||||
package oas
|
package oas
|
||||||
|
|
||||||
type CreatePostBadRequest struct {
|
type CreateShortURLBadRequest struct {
|
||||||
Message OptString `json:"message"`
|
Message OptString `json:"message"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetMessage returns the value of Message.
|
// GetMessage returns the value of Message.
|
||||||
func (s *CreatePostBadRequest) GetMessage() OptString {
|
func (s *CreateShortURLBadRequest) GetMessage() OptString {
|
||||||
return s.Message
|
return s.Message
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetMessage sets the value of Message.
|
// SetMessage sets the value of Message.
|
||||||
func (s *CreatePostBadRequest) SetMessage(val OptString) {
|
func (s *CreateShortURLBadRequest) SetMessage(val OptString) {
|
||||||
s.Message = val
|
s.Message = val
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*CreatePostBadRequest) createPostRes() {}
|
func (*CreateShortURLBadRequest) createShortURLRes() {}
|
||||||
|
|
||||||
type CreatePostCreated struct {
|
type CreateShortURLCreated struct {
|
||||||
// Created shorten URL. Going to this URL should redirect to URL from request body.
|
// Created shorten URL. Going to this URL should redirect to URL from request body.
|
||||||
Shorten OptString `json:"shorten"`
|
Shorten OptString `json:"shorten"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetShorten returns the value of Shorten.
|
// GetShorten returns the value of Shorten.
|
||||||
func (s *CreatePostCreated) GetShorten() OptString {
|
func (s *CreateShortURLCreated) GetShorten() OptString {
|
||||||
return s.Shorten
|
return s.Shorten
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetShorten sets the value of Shorten.
|
// SetShorten sets the value of Shorten.
|
||||||
func (s *CreatePostCreated) SetShorten(val OptString) {
|
func (s *CreateShortURLCreated) SetShorten(val OptString) {
|
||||||
s.Shorten = val
|
s.Shorten = val
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*CreatePostCreated) createPostRes() {}
|
func (*CreateShortURLCreated) createShortURLRes() {}
|
||||||
|
|
||||||
type CreatePostReq struct {
|
type CreateShortURLReq struct {
|
||||||
// URL to shorten.
|
// URL to shorten.
|
||||||
URL string `json:"url"`
|
URL string `json:"url"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetURL returns the value of URL.
|
// GetURL returns the value of URL.
|
||||||
func (s *CreatePostReq) GetURL() string {
|
func (s *CreateShortURLReq) GetURL() string {
|
||||||
return s.URL
|
return s.URL
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetURL sets the value of URL.
|
// SetURL sets the value of URL.
|
||||||
func (s *CreatePostReq) SetURL(val string) {
|
func (s *CreateShortURLReq) SetURL(val string) {
|
||||||
s.URL = val
|
s.URL = val
|
||||||
}
|
}
|
||||||
|
|
||||||
// HashGetNotFound is response for HashGet operation.
|
|
||||||
type HashGetNotFound struct{}
|
|
||||||
|
|
||||||
func (*HashGetNotFound) hashGetRes() {}
|
|
||||||
|
|
||||||
// HashGetTemporaryRedirect is response for HashGet operation.
|
|
||||||
type HashGetTemporaryRedirect struct {
|
|
||||||
Location OptString
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetLocation returns the value of Location.
|
|
||||||
func (s *HashGetTemporaryRedirect) GetLocation() OptString {
|
|
||||||
return s.Location
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetLocation sets the value of Location.
|
|
||||||
func (s *HashGetTemporaryRedirect) SetLocation(val OptString) {
|
|
||||||
s.Location = val
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*HashGetTemporaryRedirect) hashGetRes() {}
|
|
||||||
|
|
||||||
// NewOptString returns new OptString with value set to v.
|
// NewOptString returns new OptString with value set to v.
|
||||||
func NewOptString(v string) OptString {
|
func NewOptString(v string) OptString {
|
||||||
return OptString{
|
return OptString{
|
||||||
|
@ -117,3 +95,25 @@ func (o OptString) Or(d string) string {
|
||||||
}
|
}
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RedirectLongURLNotFound is response for RedirectLongURL operation.
|
||||||
|
type RedirectLongURLNotFound struct{}
|
||||||
|
|
||||||
|
func (*RedirectLongURLNotFound) redirectLongURLRes() {}
|
||||||
|
|
||||||
|
// RedirectLongURLTemporaryRedirect is response for RedirectLongURL operation.
|
||||||
|
type RedirectLongURLTemporaryRedirect struct {
|
||||||
|
Location OptString
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetLocation returns the value of Location.
|
||||||
|
func (s *RedirectLongURLTemporaryRedirect) GetLocation() OptString {
|
||||||
|
return s.Location
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLocation sets the value of Location.
|
||||||
|
func (s *RedirectLongURLTemporaryRedirect) SetLocation(val OptString) {
|
||||||
|
s.Location = val
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*RedirectLongURLTemporaryRedirect) redirectLongURLRes() {}
|
||||||
|
|
|
@ -8,16 +8,18 @@ import (
|
||||||
|
|
||||||
// Handler handles operations described by OpenAPI v3 specification.
|
// Handler handles operations described by OpenAPI v3 specification.
|
||||||
type Handler interface {
|
type Handler interface {
|
||||||
// CreatePost implements POST /create operation.
|
// CreateShortURL implements createShortURL operation.
|
||||||
|
//
|
||||||
|
// Create a shorten URL.
|
||||||
//
|
//
|
||||||
// POST /create
|
// POST /create
|
||||||
CreatePost(ctx context.Context, req *CreatePostReq) (CreatePostRes, error)
|
CreateShortURL(ctx context.Context, req *CreateShortURLReq) (CreateShortURLRes, error)
|
||||||
// HashGet implements GET /{hash} operation.
|
// RedirectLongURL implements redirectLongURL operation.
|
||||||
//
|
//
|
||||||
// Redirect client to long URL.
|
// Redirect client to long URL.
|
||||||
//
|
//
|
||||||
// GET /{hash}
|
// GET /{hash}
|
||||||
HashGet(ctx context.Context, params HashGetParams) (HashGetRes, error)
|
RedirectLongURL(ctx context.Context, params RedirectLongURLParams) (RedirectLongURLRes, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Server implements http server based on OpenAPI v3 specification and
|
// Server implements http server based on OpenAPI v3 specification and
|
||||||
|
|
|
@ -13,18 +13,20 @@ type UnimplementedHandler struct{}
|
||||||
|
|
||||||
var _ Handler = UnimplementedHandler{}
|
var _ Handler = UnimplementedHandler{}
|
||||||
|
|
||||||
// CreatePost implements POST /create operation.
|
// CreateShortURL implements createShortURL operation.
|
||||||
|
//
|
||||||
|
// Create a shorten URL.
|
||||||
//
|
//
|
||||||
// POST /create
|
// POST /create
|
||||||
func (UnimplementedHandler) CreatePost(ctx context.Context, req *CreatePostReq) (r CreatePostRes, _ error) {
|
func (UnimplementedHandler) CreateShortURL(ctx context.Context, req *CreateShortURLReq) (r CreateShortURLRes, _ error) {
|
||||||
return r, ht.ErrNotImplemented
|
return r, ht.ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
// HashGet implements GET /{hash} operation.
|
// RedirectLongURL implements redirectLongURL operation.
|
||||||
//
|
//
|
||||||
// Redirect client to long URL.
|
// Redirect client to long URL.
|
||||||
//
|
//
|
||||||
// GET /{hash}
|
// GET /{hash}
|
||||||
func (UnimplementedHandler) HashGet(ctx context.Context, params HashGetParams) (r HashGetRes, _ error) {
|
func (UnimplementedHandler) RedirectLongURL(ctx context.Context, params RedirectLongURLParams) (r RedirectLongURLRes, _ error) {
|
||||||
return r, ht.ErrNotImplemented
|
return r, ht.ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
29
main.go
29
main.go
|
@ -1,7 +1,32 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import "fmt"
|
import (
|
||||||
|
"context"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/babariviere/short/internal/api"
|
||||||
|
"github.com/babariviere/short/internal/db"
|
||||||
|
"github.com/babariviere/short/internal/oas"
|
||||||
|
"github.com/jackc/pgx/v5"
|
||||||
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
fmt.Println("Hello, short!")
|
psql, err := pgx.Connect(context.Background(), "postgres://short:short@localhost:5432/short")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("cannot connect to database: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
queries := db.New(psql)
|
||||||
|
handler := api.NewHandler(queries)
|
||||||
|
|
||||||
|
srv, err := oas.NewServer(handler)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed te create OpenAPI server: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("Listening on :8080")
|
||||||
|
if err = http.ListenAndServe(":8080", srv); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ paths:
|
||||||
"404":
|
"404":
|
||||||
description: Not Found
|
description: Not Found
|
||||||
description: Redirect client to long URL.
|
description: Redirect client to long URL.
|
||||||
|
operationId: redirectLongURL
|
||||||
parameters:
|
parameters:
|
||||||
- schema:
|
- schema:
|
||||||
type: string
|
type: string
|
||||||
|
@ -64,3 +65,5 @@ paths:
|
||||||
Example 1:
|
Example 1:
|
||||||
value:
|
value:
|
||||||
message: URL already exist.
|
message: URL already exist.
|
||||||
|
description: Create a shorten URL.
|
||||||
|
operationId: createShortURL
|
||||||
|
|
Loading…
Reference in a new issue