<commit_before>// Copyright 2017, 2020 <NAME>
//
//
//    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 grpcer

import (
	"bytes"
	"context"
	"errors"
	"fmt"
	"io"
	"net/http"
	"path"
	"reflect"
	"strings"
	"sync"
	"time"
	"unicode"
	"unicode/utf8"
	"unsafe"

	jsoniter "github.com/json-iterator/go"
	"github.com/json-iterator/go/extra"
	"github.com/mitchellh/mapstructure"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
)

var DefaultTimeout = 5 * time.Minute
var MaxLogWidth = 1 << 10

type JSONHandler struct {
	Client
	MergeStreams bool
	Log          func(...interface{}) error
	Timeout      time.Duration
}

func jsonError(w http.ResponseWriter, errMsg string, code int) {
	w.Header().Set("Content-Type", "application/json")
	if code == 0 {
		code = http.StatusInternalServerError
	}
	w.WriteHeader(code)
	e := struct {
		Error string
	}{Error: errMsg}
	jsoniter.NewEncoder(w).Encode(e)
}

func (h JSONHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	Log := h.Log
	if Log == nil {
		Log = func(...interface{}) error { return nil }
	}
	name := path.Base(r.URL.Path)
	Log("name", name)
	inp := h.Input(name)
	if inp == nil {
		jsonError(w, fmt.Sprintf("No unmarshaler for %q.", name), http.StatusNotFound)
		return
	}
	buf := bufPool.Get().(*bytes.Buffer)
	defer func() {
		buf.Reset()
		bufPool.Put(buf)
	}()

	buf.Reset()
	err := jsoniter.NewDecoder(io.TeeReader(r.Body, buf)).Decode(inp)
	Log("body", buf.String())
	if err != nil {
		err = fmt.Errorf("%s: %w", buf.String(), err)
		Log("got", buf.String(), "inp", inp, "error", err)
		m := mapPool.Get().(map[string]interface{})
		defer func() {
			for k := range m {
				delete(m, k)
			}
			mapPool.Put(m)
		}()
		err := jsoniter.NewDecoder(
			io.MultiReader(bytes.NewReader(buf.Bytes()), r.Body),
		).Decode(&m)
		if err != nil {
			jsonError(w, fmt.Sprintf("decode %s: %s", buf.String(), err), http.StatusBadRequest)
			return
		}
		buf.Reset()

		// mapstruct
		for k, v := range m {
			if s, ok := v.(string); ok && s == "" {
				delete(m, k)
				continue
			}
			f, _ := utf8.DecodeRune([]byte(k))
			if unicode.IsLower(f) {
				m[CamelCase(k)] = v
			}
		}
		if err := mapstructure.WeakDecode(m, inp); err != nil {
			jsonError(w, fmt.Sprintf("WeakDecode(%#v): %s", m, err), http.StatusBadRequest)
			return
		}
	}
	buf.Reset()
	jenc := jsoniter.NewEncoder(buf)
	_ = jenc.Encode(inp)
	ctx := r.Context()
	{
		u, p, ok := r.BasicAuth()
		Log("inp", buf.String(), "username", u)
		if ok {
			ctx = WithBasicAuth(ctx, u, p)
		}
	}
	if _, ok := ctx.Deadline(); !ok {
		timeout := h.Timeout
		if timeout == 0 {
			timeout = DefaultTimeout
		}
		if timeout > 0 {
			var cancel context.CancelFunc
			ctx, cancel = context.WithTimeout(ctx, timeout)
			defer cancel()
		}
	}
	recv, err := h.Call(name, ctx, inp)
	if err != nil {<commit_msg>jsonrpc: Log context deadline<commit_after>// Copyright 2017, 2020 <NAME>
//
//
//    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 grpcer

import (
	"bytes"
	"context"
	"errors"
	"fmt"
	"io"
	"net/http"
	"path"
	"reflect"
	"strings"
	"sync"
	"time"
	"unicode"
	"unicode/utf8"
	"unsafe"

	jsoniter "github.com/json-iterator/go"
	"github.com/json-iterator/go/extra"
	"github.com/mitchellh/mapstructure"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
)

var DefaultTimeout = 5 * time.Minute
var MaxLogWidth = 1 << 10

type JSONHandler struct {
	Client
	MergeStreams bool
	Log          func(...interface{}) error
	Timeout      time.Duration
}

func jsonError(w http.ResponseWriter, errMsg string, code int) {
	w.Header().Set("Content-Type", "application/json")
	if code == 0 {
		code = http.StatusInternalServerError
	}
	w.WriteHeader(code)
	e := struct {
		Error string
	}{Error: errMsg}
	jsoniter.NewEncoder(w).Encode(e)
}

func (h JSONHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	Log := h.Log
	if Log == nil {
		Log = func(...interface{}) error { return nil }
	}
	name := path.Base(r.URL.Path)
	Log("name", name)
	inp := h.Input(name)
	if inp == nil {
		jsonError(w, fmt.Sprintf("No unmarshaler for %q.", name), http.StatusNotFound)
		return
	}
	buf := bufPool.Get().(*bytes.Buffer)
	defer func() {
		buf.Reset()
		bufPool.Put(buf)
	}()

	buf.Reset()
	err := jsoniter.NewDecoder(io.TeeReader(r.Body, buf)).Decode(inp)
	Log("body", buf.String())
	if err != nil {
		err = fmt.Errorf("%s: %w", buf.String(), err)
		Log("got", buf.String(), "inp", inp, "error", err)
		m := mapPool.Get().(map[string]interface{})
		defer func() {
			for k := range m {
				delete(m, k)
			}
			mapPool.Put(m)
		}()
		err := jsoniter.NewDecoder(
			io.MultiReader(bytes.NewReader(buf.Bytes()), r.Body),
		).Decode(&m)
		if err != nil {
			jsonError(w, fmt.Sprintf("decode %s: %s", buf.String(), err), http.StatusBadRequest)
			return
		}
		buf.Reset()

		// mapstruct
		for k, v := range m {
			if s, ok := v.(string); ok && s == "" {
				delete(m, k)
				continue
			}
			f, _ := utf8.DecodeRune([]byte(k))
			if unicode.IsLower(f) {
				m[CamelCase(k)] = v
			}
		}
		if err := mapstructure.WeakDecode(m, inp); err != nil {
			jsonError(w, fmt.Sprintf("WeakDecode(%#v): %s", m, err), http.StatusBadRequest)
			return
		}
	}
	buf.Reset()
	jenc := jsoniter.NewEncoder(buf)
	_ = jenc.Encode(inp)
	ctx := r.Context()
	{
		u, p, ok := r.BasicAuth()
		Log("inp", buf.String(), "username", u)
		if ok {
			ctx = WithBasicAuth(ctx, u, p)
		}
	}
	if _, ok := ctx.Deadline(); !ok {
		timeout := h.Timeout
		if timeout == 0 {
			timeout = DefaultTimeout
		}
		if timeout > 0 {
			var cancel context.CancelFunc
			ctx, cancel = context.WithTimeout(ctx, timeout)
			defer cancel()
		}
	}
	dl, _ := ctx.Deadline() 
	Log("call", name, "deadline", dl)

	recv, err := h.Call(name, ctx, inp)
	if err != nil {
{'fraction_non_alphanumeric': 0.16456068175139582, 'fraction_numerical': 0.006171025565677344, 'mean_word_length': 3.2148606811145513, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '441553', 'n_tokens_mistral': 2687, 'n_tokens_neox': 2474, 'n_words': 649}