eintopf.info@v0.13.16/service/eventsearch/transport.go (about)

     1  // Copyright (C) 2022 The Eintopf authors
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU Affero General Public License as
     5  // published by the Free Software Foundation, either version 3 of the
     6  // License, or (at your option) any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU Affero General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU Affero General Public License
    14  // along with this program.  If not, see <https://www.gnu.org/licenses/>.
    15  
    16  package eventsearch
    17  
    18  import (
    19  	"encoding/json"
    20  	"fmt"
    21  	"net/http"
    22  
    23  	"github.com/go-chi/chi/v5"
    24  
    25  	"eintopf.info/internal/xhttp"
    26  )
    27  
    28  // Router returns an http router for the search service.
    29  func Router(service Service) func(chi.Router) {
    30  	server := &server{service: service}
    31  	return func(r chi.Router) {
    32  		r.Options("/", xhttp.CorsHandler)
    33  
    34  		// swagger:route GET /eventsearch eventsearch eventsearch
    35  		//
    36  		// Perfomes an event search request.
    37  		//
    38  		//     Responses:
    39  		//       200: eventsearchResult
    40  		//       304:
    41  		//       400: badRequest
    42  		//       500: internalError
    43  		//       503: serviceUnavailable
    44  		r.Get("/", server.search)
    45  	}
    46  }
    47  
    48  type server struct {
    49  	service Service
    50  }
    51  
    52  func (s *server) search(w http.ResponseWriter, r *http.Request) {
    53  	if xhttp.RequestIsNotModified(r, s.service.LastModified()) {
    54  		xhttp.WriteNotModified(w, s.service.LastModified())
    55  		return
    56  	}
    57  
    58  	options, err := OptionsFromRequest(r)
    59  	if err != nil {
    60  		xhttp.WriteBadRequest(r.Context(), w, err)
    61  		return
    62  	}
    63  
    64  	result, err := s.service.Search(r.Context(), options)
    65  	if err != nil {
    66  		xhttp.WriteError(r.Context(), w, fmt.Errorf("failed to search: %s", err))
    67  		return
    68  	}
    69  	data, err := json.Marshal(result)
    70  	if err != nil {
    71  		xhttp.WriteInternalError(r.Context(), w, err)
    72  		return
    73  	}
    74  
    75  	xhttp.WriteWithLastModified(w, data, s.service.LastModified())
    76  }
    77  
    78  // OptionsFromRequest parses Options from a http.Request
    79  func OptionsFromRequest(r *http.Request) (Options, error) {
    80  	query, err := xhttp.ReadQueryString(r, "query")
    81  	if err != nil {
    82  		return Options{}, fmt.Errorf("query: %s", err)
    83  	}
    84  	sort, err := xhttp.ReadQueryString(r, "sort")
    85  	if err != nil {
    86  		return Options{}, fmt.Errorf("sort: %s", err)
    87  	}
    88  	page, err := xhttp.ReadQueryInt(r, "page")
    89  	if err != nil {
    90  		return Options{}, fmt.Errorf("page: %s", err)
    91  	}
    92  	pageSize, err := xhttp.ReadQueryInt(r, "pageSize")
    93  	if err != nil {
    94  		return Options{}, fmt.Errorf("page: %s", err)
    95  	}
    96  	filters, err := filtersFromQuery(r.URL.Query(), "")
    97  	if err != nil {
    98  		return Options{}, err
    99  	}
   100  	aggregations, err := aggregationsFromQuery(r.URL.Query())
   101  	if err != nil {
   102  		return Options{}, err
   103  	}
   104  	omit, err := xhttp.ReadQueryStringArray(r, "omit")
   105  	if err != nil {
   106  		return Options{}, fmt.Errorf("omit: %s", err)
   107  	}
   108  
   109  	return Options{
   110  		Query:        query,
   111  		Sort:         sort,
   112  		Page:         page,
   113  		PageSize:     pageSize,
   114  		Filters:      filters,
   115  		Aggregations: aggregations,
   116  		Omit:         omit,
   117  	}, nil
   118  }