0
0
Fork 0
bleve/http/mapping/mapping.go

429 lines
11 KiB
Go

// Copyright (c) 2015 Couchbase, Inc.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the
// License. You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0 Unless required by
// applicable law or agreed to in writing, software distributed under
// the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
// OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and
// limitations under the License.
package mapping
//go:generate go-bindata-assetfs -pkg=mapping ./mapping_static/...
//go:generate go fmt .
import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"log"
"net/http"
"sort"
"github.com/elazarl/go-bindata-assetfs"
"github.com/gorilla/mux"
"github.com/blevesearch/bleve"
"github.com/blevesearch/bleve/analysis"
"github.com/blevesearch/bleve/registry"
)
func AssetFS() *assetfs.AssetFS {
return assetFS()
}
// RegisterHandlers registers mapping handlers on a router at the
// given pathBase, such as at "/api".
func RegisterHandlers(router *mux.Router, pathBase string) {
router.HandleFunc(pathBase+"/_analyzerNames", ListAnalyzerNames).Methods("POST")
router.HandleFunc(pathBase+"/_datetimeParserNames", ListDateTimeParserNames).Methods("POST")
router.HandleFunc(pathBase+"/_charFilterNames", ListCharFilterNames).Methods("POST")
router.HandleFunc(pathBase+"/_charFilterTypes", ListCharFilterTypes).Methods("GET")
router.HandleFunc(pathBase+"/_tokenizerNames", ListTokenizerNames).Methods("POST")
router.HandleFunc(pathBase+"/_tokenizerTypes", ListTokenizerTypes).Methods("GET")
router.HandleFunc(pathBase+"/_tokenFilterNames", ListTokenFilterNames).Methods("POST")
router.HandleFunc(pathBase+"/_tokenFilterTypes", ListTokenFilterTypes).Methods("GET")
router.HandleFunc(pathBase+"/_tokenMapNames", ListTokenMapNames).Methods("POST")
router.HandleFunc(pathBase+"/_analyze", AnalyzerText).Methods("POST")
router.HandleFunc(pathBase+"/_validateMapping", ValidateMapping).Methods("POST")
}
func ListAnalyzerNames(w http.ResponseWriter, req *http.Request) {
indexMapping := bleve.NewIndexMapping()
// read the request body
requestBody, err := ioutil.ReadAll(req.Body)
if err != nil {
showError(w, req, fmt.Sprintf("error reading request body: %v", err), 400)
return
}
// interpret request body as index mapping
if len(requestBody) > 0 {
err := json.Unmarshal(requestBody, &indexMapping)
if err != nil {
showError(w, req, fmt.Sprintf("error parsing index mapping: %v", err), 400)
return
}
}
// built in analyzer names
_, analyzerNames := registry.AnalyzerTypesAndInstances()
// add custom analyzer names
for name := range indexMapping.CustomAnalysis.Analyzers {
analyzerNames = append(analyzerNames, name)
}
sort.Strings(analyzerNames)
rv := struct {
Status string `json:"status"`
Analyzers []string `json:"analyzers"`
}{
Status: "ok",
Analyzers: analyzerNames,
}
mustEncode(w, rv)
}
func AnalyzerText(w http.ResponseWriter, req *http.Request) {
// read the request body
requestBody, err := ioutil.ReadAll(req.Body)
if err != nil {
showError(w, req, fmt.Sprintf("error reading request body: %v", err), 400)
return
}
mapping := bleve.NewIndexMapping()
var analyzeRequest = struct {
Analyzer string `json:"analyzer"`
Text string `json:"text"`
Mapping *bleve.IndexMapping `json:"mapping"`
}{}
err = json.Unmarshal(requestBody, &analyzeRequest)
if err != nil {
showError(w, req, fmt.Sprintf("error parsing index mapping: %v", err), 400)
return
}
if analyzeRequest.Mapping != nil {
mapping = analyzeRequest.Mapping
}
ts, err := mapping.AnalyzeText(analyzeRequest.Analyzer, []byte(analyzeRequest.Text))
if err != nil {
showError(w, req, fmt.Sprintf("error analyzing text: %v", err), 400)
return
}
rv := struct {
Status string `json:"status"`
Text string `json:"text"`
TokenStream analysis.TokenStream `json:"token_stream"`
}{
Status: "ok",
Text: analyzeRequest.Text,
TokenStream: ts,
}
mustEncode(w, rv)
}
func ListDateTimeParserNames(w http.ResponseWriter, req *http.Request) {
indexMapping := bleve.NewIndexMapping()
// read the request body
requestBody, err := ioutil.ReadAll(req.Body)
if err != nil {
showError(w, req, fmt.Sprintf("error reading request body: %v", err), 400)
return
}
// interpret request body as index mapping
if len(requestBody) > 0 {
err := json.Unmarshal(requestBody, &indexMapping)
if err != nil {
showError(w, req, fmt.Sprintf("error parsing index mapping: %v", err), 400)
return
}
}
// built in char filter names
_, dateTimeParserNames := registry.DateTimeParserTypesAndInstances()
// add custom date time parser names
for name := range indexMapping.CustomAnalysis.DateTimeParsers {
dateTimeParserNames = append(dateTimeParserNames, name)
}
sort.Strings(dateTimeParserNames)
rv := struct {
Status string `json:"status"`
DateTimeParsers []string `json:"datetime_parsers"`
}{
Status: "ok",
DateTimeParsers: dateTimeParserNames,
}
mustEncode(w, rv)
}
func ListCharFilterNames(w http.ResponseWriter, req *http.Request) {
indexMapping := bleve.NewIndexMapping()
// read the request body
requestBody, err := ioutil.ReadAll(req.Body)
if err != nil {
showError(w, req, fmt.Sprintf("error reading request body: %v", err), 400)
return
}
// interpret request body as index mapping
if len(requestBody) > 0 {
err := json.Unmarshal(requestBody, &indexMapping)
if err != nil {
showError(w, req, fmt.Sprintf("error parsing index mapping: %v", err), 400)
return
}
}
// built in char filter names
_, charFilterNames := registry.CharFilterTypesAndInstances()
// add custom char filter names
for name := range indexMapping.CustomAnalysis.CharFilters {
charFilterNames = append(charFilterNames, name)
}
sort.Strings(charFilterNames)
rv := struct {
Status string `json:"status"`
CharFilters []string `json:"char_filters"`
}{
Status: "ok",
CharFilters: charFilterNames,
}
mustEncode(w, rv)
}
func ListCharFilterTypes(w http.ResponseWriter, req *http.Request) {
// built in char filter names
charFilterTypes, _ := registry.CharFilterTypesAndInstances()
sort.Strings(charFilterTypes)
rv := struct {
Status string `json:"status"`
CharFilterTypes []string `json:"char_filter_types"`
}{
Status: "ok",
CharFilterTypes: charFilterTypes,
}
mustEncode(w, rv)
}
func ListTokenizerNames(w http.ResponseWriter, req *http.Request) {
indexMapping := bleve.NewIndexMapping()
// read the request body
requestBody, err := ioutil.ReadAll(req.Body)
if err != nil {
showError(w, req, fmt.Sprintf("error reading request body: %v", err), 400)
return
}
// interpret request body as index mapping
if len(requestBody) > 0 {
err := json.Unmarshal(requestBody, &indexMapping)
if err != nil {
showError(w, req, fmt.Sprintf("error parsing index mapping: %v", err), 400)
return
}
}
// built in char filter names
_, tokenizerNames := registry.TokenizerTypesAndInstances()
// add custom char filter names
for name := range indexMapping.CustomAnalysis.Tokenizers {
tokenizerNames = append(tokenizerNames, name)
}
sort.Strings(tokenizerNames)
rv := struct {
Status string `json:"status"`
Tokenizers []string `json:"tokenizers"`
}{
Status: "ok",
Tokenizers: tokenizerNames,
}
mustEncode(w, rv)
}
func ListTokenizerTypes(w http.ResponseWriter, req *http.Request) {
// built in char filter names
tokenizerTypes, _ := registry.TokenizerTypesAndInstances()
sort.Strings(tokenizerTypes)
rv := struct {
Status string `json:"status"`
TokenizerTypes []string `json:"tokenizer_types"`
}{
Status: "ok",
TokenizerTypes: tokenizerTypes,
}
mustEncode(w, rv)
}
func ListTokenFilterNames(w http.ResponseWriter, req *http.Request) {
indexMapping := bleve.NewIndexMapping()
// read the request body
requestBody, err := ioutil.ReadAll(req.Body)
if err != nil {
showError(w, req, fmt.Sprintf("error reading request body: %v", err), 400)
return
}
// interpret request body as index mapping
if len(requestBody) > 0 {
err := json.Unmarshal(requestBody, &indexMapping)
if err != nil {
showError(w, req, fmt.Sprintf("error parsing index mapping: %v", err), 400)
return
}
}
// built in char filter names
_, tokenFilterNames := registry.TokenFilterTypesAndInstances()
// add custom char filter names
for name := range indexMapping.CustomAnalysis.TokenFilters {
tokenFilterNames = append(tokenFilterNames, name)
}
sort.Strings(tokenFilterNames)
rv := struct {
Status string `json:"status"`
TokenFilters []string `json:"token_filters"`
}{
Status: "ok",
TokenFilters: tokenFilterNames,
}
mustEncode(w, rv)
}
func ListTokenFilterTypes(w http.ResponseWriter, req *http.Request) {
// built in char filter names
tokenFilterTypes, _ := registry.TokenFilterTypesAndInstances()
sort.Strings(tokenFilterTypes)
rv := struct {
Status string `json:"status"`
TokenFilterTypes []string `json:"token_filter_types"`
}{
Status: "ok",
TokenFilterTypes: tokenFilterTypes,
}
mustEncode(w, rv)
}
func ListTokenMapNames(w http.ResponseWriter, req *http.Request) {
indexMapping := bleve.NewIndexMapping()
// read the request body
requestBody, err := ioutil.ReadAll(req.Body)
if err != nil {
showError(w, req, fmt.Sprintf("error reading request body: %v", err), 400)
return
}
// interpret request body as index mapping
if len(requestBody) > 0 {
err := json.Unmarshal(requestBody, &indexMapping)
if err != nil {
showError(w, req, fmt.Sprintf("error parsing index mapping: %v", err), 400)
return
}
}
// built in char filter names
_, tokenMapNames := registry.TokenMapTypesAndInstances()
// add custom char map names
for name := range indexMapping.CustomAnalysis.TokenMaps {
tokenMapNames = append(tokenMapNames, name)
}
sort.Strings(tokenMapNames)
rv := struct {
Status string `json:"status"`
TokenMaps []string `json:"token_maps"`
}{
Status: "ok",
TokenMaps: tokenMapNames,
}
mustEncode(w, rv)
}
func ValidateMapping(w http.ResponseWriter, req *http.Request) {
indexMapping := bleve.NewIndexMapping()
// read the request body
requestBody, err := ioutil.ReadAll(req.Body)
if err != nil {
showError(w, req, fmt.Sprintf("error reading request body: %v", err), 400)
return
}
// interpret request body as index mapping
if len(requestBody) > 0 {
err := json.Unmarshal(requestBody, &indexMapping)
if err != nil {
showError(w, req, fmt.Sprintf("error parsing index mapping: %v", err), 400)
return
}
}
rv := struct {
Status string `json:"status"`
}{
Status: "ok",
}
mustEncode(w, rv)
}
func showError(w http.ResponseWriter, r *http.Request,
msg string, code int) {
log.Printf("Reporting error %v/%v", code, msg)
http.Error(w, msg, code)
}
func mustEncode(w io.Writer, i interface{}) {
if headered, ok := w.(http.ResponseWriter); ok {
headered.Header().Set("Cache-Control", "no-cache")
headered.Header().Set("Content-type", "application/json")
}
e := json.NewEncoder(w)
if err := e.Encode(i); err != nil {
panic(err)
}
}