Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Misc #109

Merged
merged 8 commits into from
Jan 26, 2024
Merged

Misc #109

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion .github/workflows/lint-go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,16 @@ jobs:

- uses: actions/checkout@v3

- name: Tidy
- name: tidy
uses: katexochen/go-tidy-check@v2

- name: check optimal struct field alignment (for crucial structs)
run: |
GOPATH_BIN=$(go env GOPATH)/bin
export PATH="/usr/share/miniconda/bin:${GOPATH_BIN}:${PATH}"
go install github.com/dkorunic/betteralign/cmd/betteralign@latest
betteralign ./ogc/features/domain

- name: golangci-lint
uses: golangci/golangci-lint-action@v3
with:
Expand Down
4 changes: 3 additions & 1 deletion assets/i18n/active.en.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,10 @@ CollectionsText = """
This API offers one or more collections that enable differentiation by splitting the PDOK dataset into \
various objects that can be called separately through for instance features or tiles."""
Tiles = "Tiles"
TilesText = """
TilesTextHTML = """
This entire dataset is available as vector tiles in multiple projections. One or more <a href="styles">styles</a> are also available."""
TilesTextPlain = """
This entire dataset is available as vector tiles in multiple projections. One or more styles are also available."""
Styles = "Styles"
StylesText = """
One or more official styles as specified by the supplier. Styles are made available in the Mapbox format."""
Expand Down
5 changes: 4 additions & 1 deletion assets/i18n/active.nl.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,12 @@ Deze API biedt één of meerdere collecties waarmee differentiatie gemaakt kan w
dataset van PDOK op te splitsen in verschillende objecten die bijvoorbeeld via features of \
tiles separaat aangeroepen kunnen worden."""
Tiles = "Tiles"
TilesText = """
TilesTextHTML = """
Deze dataset wordt beschikbaar gesteld als vector tiles in meerdere projecties. Ook worden er \
&eacute;&eacute;n of meerdere <a href="styles">styles</a> beschikbaar gesteld."""
TilesTextPlain = """
Deze dataset wordt beschikbaar gesteld als vector tiles in meerdere projecties. Ook worden er \
één of meerdere styles beschikbaar gesteld."""
Styles = "Styles"
StylesText = """
Betreft één of meerdere officiële styles van/door de aanbieder gespecificeerd. \
Expand Down
2 changes: 1 addition & 1 deletion engine/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func TestNewConfig(t *testing.T) {
configFile: "engine/testdata/config_invalid.yaml",
},
wantErr: true,
wantErrMsg: "invalid URI",
wantErrMsg: "validation for 'Version' failed on the 'semver' tag",
},
}
for _, tt := range tests {
Expand Down
12 changes: 6 additions & 6 deletions engine/contentnegotiation.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ var (
"application/javascript",
"image/svg+xml",
}
StyleFormatExtension = map[string]string{
FormatMapboxStyle: ".json",
FormatCustomStyle: ".style",
FormatSLD: ".sld",
}
)

type ContentNegotiation struct {
Expand Down Expand Up @@ -106,12 +111,7 @@ func (cn *ContentNegotiation) GetSupportedStyleFormats() []string {
}

func (cn *ContentNegotiation) GetStyleFormatExtension(format string) string {
extensionsByFormat := map[string]string{
FormatMapboxStyle: ".json",
FormatCustomStyle: ".style",
FormatSLD: ".sld",
}
if extension, exists := extensionsByFormat[format]; exists {
if extension, exists := StyleFormatExtension[format]; exists {
return extension
}
return ""
Expand Down
6 changes: 3 additions & 3 deletions engine/contentnegotiation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ func testLanguage(t *testing.T, cn *ContentNegotiation, acceptLanguageHeader str
if err != nil {
t.Fatal(err)
}
language := cn.NegotiateLanguage(httptest.NewRecorder(), req)
if language != expectedLanguage {
t.Fatalf("Expected %v for input %s, got %v", expectedLanguage, givenURL, language)
lang := cn.NegotiateLanguage(httptest.NewRecorder(), req)
if lang != expectedLanguage {
t.Fatalf("Expected %v for input %s, got %v", expectedLanguage, givenURL, lang)
}
}
12 changes: 1 addition & 11 deletions engine/resources_endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,7 @@ import (
"github.com/go-chi/chi/v5"
)

type ResourcesEndpoint struct {
engine *Engine
}

func newResourcesEndpoint(e *Engine) *ResourcesEndpoint {
resources := &ResourcesEndpoint{
engine: e,
}

func newResourcesEndpoint(e *Engine) {
// Serve static assets either from local storage or through reverse proxy
if resourcesDir := e.Config.Resources.Directory; resourcesDir != "" {
resourcesPath := strings.TrimSuffix(resourcesDir, "/resources")
Expand All @@ -35,6 +27,4 @@ func newResourcesEndpoint(e *Engine) *ResourcesEndpoint {
e.ReverseProxy(w, r, target, true, "")
})
}

return resources
}
14 changes: 13 additions & 1 deletion engine/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,20 @@ func newRouter(version string, enableTrailingSlash bool, enableCORS bool) *chi.M
MaxAge: int((time.Hour * 24).Seconds()),
}))
}
// implements https://gitdocumentatie.logius.nl/publicatie/api/adr/#api-57
// some GIS clients don't sent proper CORS preflight requests, still respond with OK for any OPTIONS request
router.Use(optionsFallback)
// add semver header, implements https://gitdocumentatie.logius.nl/publicatie/api/adr/#api-57
router.Use(middleware.SetHeader(HeaderAPIVersion, version))
router.Use(middleware.Compress(5, CompressibleMediaTypes...)) // enable gzip responses
return router
}

func optionsFallback(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method == http.MethodOptions {
w.WriteHeader(http.StatusOK)
return
}
next.ServeHTTP(w, r)
})
}
6 changes: 3 additions & 3 deletions engine/testdata/config_invalid.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
---
version: 1.0.2
version: 1.0.2.6.8
title: Invalid config file
abstract: With wrong base url
baseUrl: this_is_not_a_valid_url
abstract: Version is invalid according to semver validation.
baseUrl: http://test.example
serviceIdentifier: Min
license:
name: MIT
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ require (
github.com/stretchr/testify v1.8.4
github.com/urfave/cli/v2 v2.26.0
github.com/writeas/go-strip-markdown/v2 v2.1.1
go.uber.org/automaxprocs v1.5.3
golang.org/x/text v0.14.0
gopkg.in/yaml.v3 v3.0.1
)
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX
github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
github.com/qustavo/sqlhooks/v2 v2.1.0 h1:54yBemHnGHp/7xgT+pxwmIlMSDNYKx5JW5dfRAiCZi0=
github.com/qustavo/sqlhooks/v2 v2.1.0/go.mod h1:aMREyKo7fOKTwiLuWPsaHRXEmtqG4yREztO0idF83AU=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
Expand All @@ -115,6 +117,8 @@ github.com/writeas/go-strip-markdown/v2 v2.1.1 h1:hAxUM21Uhznf/FnbVGiJciqzska6iL
github.com/writeas/go-strip-markdown/v2 v2.1.1/go.mod h1:UvvgPJgn1vvN8nWuE5e7v/+qmDu3BSVnKAB6Gl7hFzA=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
go.uber.org/automaxprocs v1.5.3 h1:kWazyxZUrS3Gs4qUpbwo5kEIMGe/DAvi5Z4tl2NW4j8=
go.uber.org/automaxprocs v1.5.3/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
Expand Down
2 changes: 2 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import (
"github.com/PDOK/gokoala/ogc/styles"
"github.com/PDOK/gokoala/ogc/tiles"
"github.com/urfave/cli/v2"

_ "go.uber.org/automaxprocs"
)

var (
Expand Down
2 changes: 1 addition & 1 deletion ogc/common/core/templates/landing-page.go.html
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ <h5 class="card-header">
</h5>
<div class="card-body">
<p>
{{ i18n "TilesText" }}
{{ i18n "TilesTextHTML" }}
{{ i18n "AvailableIn" }}
</p>
<small class="text-body-secondary">{{ i18n "ViewAs" }} <a href="tiles?f=json" target="_blank">JSON</a></small>
Expand Down
12 changes: 6 additions & 6 deletions ogc/features/domain/cursor.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ type EncodedCursor string

// DecodedCursor the cursor values after decoding EncodedCursor
type DecodedCursor struct {
FID int64
FiltersChecksum []byte
FID int64
}

// PrevNextFID previous and next feature id (fid) to encode in cursor.
Expand Down Expand Up @@ -62,19 +62,19 @@ func encodeCursor(fid int64, filtersChecksum []byte) EncodedCursor {
func (c EncodedCursor) Decode(filtersChecksum []byte) DecodedCursor {
value := string(c)
if value == "" {
return DecodedCursor{0, filtersChecksum}
return DecodedCursor{filtersChecksum, 0}
}

decoded, err := base64.URLEncoding.DecodeString(value)
if err != nil || len(decoded) == 0 {
log.Printf("decoding cursor value '%v' failed, defaulting to first page", decoded)
return DecodedCursor{0, filtersChecksum}
return DecodedCursor{filtersChecksum, 0}
}

decodedFid, decodedChecksum, found := bytes.Cut(decoded, []byte{separator})
if !found {
log.Printf("cursor '%v' doesn't contain expected separator %c", decoded, separator)
return DecodedCursor{0, filtersChecksum}
return DecodedCursor{filtersChecksum, 0}
}

// feature id
Expand All @@ -87,10 +87,10 @@ func (c EncodedCursor) Decode(filtersChecksum []byte) DecodedCursor {
// checksum
if !bytes.Equal(decodedChecksum, filtersChecksum) {
log.Printf("filters in query params have changed during pagination, resetting to first page")
return DecodedCursor{0, filtersChecksum}
return DecodedCursor{filtersChecksum, 0}
}

return DecodedCursor{fid, filtersChecksum}
return DecodedCursor{filtersChecksum, fid}
}

func (c EncodedCursor) String() string {
Expand Down
21 changes: 11 additions & 10 deletions ogc/features/domain/geojson.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,31 +14,32 @@ func (fc *featureCollectionType) UnmarshalJSON([]byte) error { return nil }

// FeatureCollection is a GeoJSON FeatureCollection with extras such as links
type FeatureCollection struct {
Links []Link `json:"links,omitempty"`
Type featureCollectionType `json:"type"`
Timestamp string `json:"timeStamp,omitempty"`
Links []Link `json:"links,omitempty"`

Features []*Feature `json:"features"`

NumberReturned int `json:"numberReturned"`
Timestamp string `json:"timeStamp,omitempty"`
Type featureCollectionType `json:"type"`
Features []*Feature `json:"features"`
NumberReturned int `json:"numberReturned"`
}

// Feature is a GeoJSON Feature with extras such as links
type Feature struct {
// we overwrite ID since we want to make it a required attribute. We also expect feature ids to be
// auto-incrementing integers (which is the default in geopackages) since we use it for cursor-based pagination.
ID int64 `json:"id"`
geojson.Feature
Links []Link `json:"links,omitempty"`

geojson.Feature
// we overwrite ID since we want to make it a required attribute. We also expect feature ids to be
// auto-incrementing integers (which is the default in geopackages) since we use it for cursor-based pagination.
ID int64 `json:"id"`
}

// Link according to RFC 8288, https://datatracker.ietf.org/doc/html/rfc8288
type Link struct {
Length int64 `json:"length,omitempty"`
Rel string `json:"rel"`
Title string `json:"title,omitempty"`
Type string `json:"type,omitempty"`
Href string `json:"href"`
Hreflang string `json:"hreflang,omitempty"`
Length int64 `json:"length,omitempty"`
Templated bool `json:"templated,omitempty"`
}
30 changes: 15 additions & 15 deletions ogc/features/domain/jsonfg.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,27 +17,27 @@ func (ft *featureType) MarshalJSON() ([]byte, error) {
func (ft *featureType) UnmarshalJSON([]byte) error { return nil }

type JSONFGFeatureCollection struct {
Links []Link `json:"links,omitempty"`
NumberReturned int `json:"numberReturned"`
Timestamp string `json:"timeStamp,omitempty"`
Type featureCollectionType `json:"type"`
ConformsTo []string `json:"conformsTo"`
Timestamp string `json:"timeStamp,omitempty"`
CoordRefSys string `json:"coordRefSys"`
Links []Link `json:"links,omitempty"`
ConformsTo []string `json:"conformsTo"`
Features []*JSONFGFeature `json:"features"`
NumberReturned int `json:"numberReturned"`
}

type JSONFGFeature struct {
// We expect feature ids to be auto-incrementing integers (which is the default in geopackages)
// since we use it for cursor-based pagination.
ID int64 `json:"id"`
Links []Link `json:"links,omitempty"`
Type featureType `json:"type"`
ConformsTo []string `json:"conformsTo,omitempty"`
CoordRefSys string `json:"coordRefSys,omitempty"`
Time any `json:"time"`
Type featureType `json:"type"`
Time any `json:"time"`
// we don't implement the JSON-FG "3D" conformance class. So Place only
// supports simple/2D geometries, no 3D geometries like Polyhedron, Prism, etc.
Place geom.Geometry `json:"place"` // may only contain non-WGS84 geometries
Geometry geom.Geometry `json:"geometry"` // may only contain WGS84 geometries
Properties map[string]any `json:"properties"`
Place geom.Geometry `json:"place"` // may only contain non-WGS84 geometries
Geometry geom.Geometry `json:"geometry"` // may only contain WGS84 geometries
Properties map[string]any `json:"properties"`
CoordRefSys string `json:"coordRefSys,omitempty"`
Links []Link `json:"links,omitempty"`
ConformsTo []string `json:"conformsTo,omitempty"`
// We expect feature ids to be auto-incrementing integers (which is the default in geopackages)
// since we use it for cursor-based pagination.
ID int64 `json:"id"`
}
2 changes: 1 addition & 1 deletion ogc/tiles/templates/tiles.go.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ <h1 class="title">{{ .Config.Title }} - {{ i18n "Tiles" }}</h1>
<div class="row py-3">
<div class="col-md-12">
<p>
{{ i18n "TilesText" }}
{{ i18n "TilesTextHTML" }}
</p>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion ogc/tiles/templates/tiles.go.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
{{ if .Config.OgcAPI.Tiles }}
{{$baseUrl := .Config.BaseURL}}
"title": "{{ .Config.Title }} - Tiles",
"description": "Deze hele dataset is beschikbaar via OGC API Tiles. Tiles kunnen zowel vector als raster data bevatten en in meerdere projecties beschikbaar worden gesteld. In het geval van vector tiles biedt PDOK ook styles aan.",
"description": "{{ i18n "TilesTextPlain" }}",
"links": [
{
"rel": "self",
Expand Down
Loading