<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"

	"github.com/braintree/manners"
)

func NewStartApp(port string, rootDir string) *StartApp {
	return &StartApp{
		RootDir: rootDir,
		Port:    port,
	}
}

type StartApp struct {
	RootDir       string
	Port          string
	EndpointCache EndpointCache
}

/////////////////////////////////////////////////////
// Check the basic settings and register handlers
/////////////////////////////////////////////////////

func (s *StartApp) Setup() error {

	// Check that the path exists
	path, err := os.Stat(s.RootDir)

	if os.IsNotExist(err) {
		return fmt.Errorf("no such file or directory: %s", s.RootDir)
	}

	if !path.IsDir() {
		return fmt.Errorf("Path is not a directory %s", s.RootDir)
	}

	http.HandleFunc("/", s.Handle)

	return nil
}

/////////////////////////////////////////////////////
// Given an exit channel, run everything
/////////////////////////////////////////////////////

func (s *StartApp) Run(exit chan interface{}) {
	go manners.ListenAndServe(fmt.Sprintf(":%s", s.Port), nil)

	<-exit
}

/////////////////////////////////////////////////////
// This is the main handler
/////////////////////////////////////////////////////

func (s *StartApp) Handle(w http.ResponseWriter, r *http.Request) {

	ep, err := s.fetchEndpoint(r.URL.Path[1:], r.Method)

	if err != nil {
		w.Header().Set("Ersatz-Error", err.Error())
		w.WriteHeader(http.StatusNotFound)
		return
	}

	body, err := json.Marshal(ep.Body)

	if err != nil {
		w.Header().Set("Ersatz-Error", err.Error())
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	w.Header().Set("Content-Length", fmt.Sprintf("%d", len(body)))

	for k, v := range ep.Headers {
		w.Header().Set(k, v)
	}

	w.Write(body)
}

/////////////////////////////////////////////////////
// Fetch a given endpoint by method and url
/////////////////////////////////////////////////////

func (s *StartApp) fetchEndpoint(url, method string) (*Endpoint, error) {

	variant := "default"

	// Check to see if the request is in the cache
	if c, exists := s.EndpointCache[EndpointIndex{url, method, variant}]; exists {
		return c, nil
	}

	file, e := ioutil.ReadFile(fmt.Sprintf("%s/%s/%s/%s.json", s.RootDir, url, method, variant))

	if e != nil {
		return nil, e
	}

	ep := NewEndpoint()

	if e := json.Unmarshal(file, ep); e != nil {
		return nil, e
	}
<commit_msg>use filepath.Join instead of sprintf<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"

	"github.com/braintree/manners"
)

func NewStartApp(port string, rootDir string) *StartApp {
	return &StartApp{
		RootDir: rootDir,
		Port:    port,
	}
}

type StartApp struct {
	RootDir       string
	Port          string
	EndpointCache EndpointCache
}

/////////////////////////////////////////////////////
// Check the basic settings and register handlers
/////////////////////////////////////////////////////

func (s *StartApp) Setup() error {

	// Check that the path exists
	path, err := os.Stat(s.RootDir)

	if os.IsNotExist(err) {
		return fmt.Errorf("no such file or directory: %s", s.RootDir)
	}

	if !path.IsDir() {
		return fmt.Errorf("Path is not a directory %s", s.RootDir)
	}

	http.HandleFunc("/", s.Handle)

	return nil
}

/////////////////////////////////////////////////////
// Given an exit channel, run everything
/////////////////////////////////////////////////////

func (s *StartApp) Run(exit chan interface{}) {
	go manners.ListenAndServe(fmt.Sprintf(":%s", s.Port), nil)

	<-exit
}

/////////////////////////////////////////////////////
// This is the main handler
/////////////////////////////////////////////////////

func (s *StartApp) Handle(w http.ResponseWriter, r *http.Request) {

	ep, err := s.fetchEndpoint(r.URL.Path[1:], r.Method)

	if err != nil {
		w.Header().Set("Ersatz-Error", err.Error())
		w.WriteHeader(http.StatusNotFound)
		return
	}

	body, err := json.Marshal(ep.Body)

	if err != nil {
		w.Header().Set("Ersatz-Error", err.Error())
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	w.Header().Set("Content-Length", fmt.Sprintf("%d", len(body)))

	for k, v := range ep.Headers {
		w.Header().Set(k, v)
	}

	w.Write(body)
}

/////////////////////////////////////////////////////
// Fetch a given endpoint by method and url
/////////////////////////////////////////////////////

func (s *StartApp) fetchEndpoint(url, method string) (*Endpoint, error) {

	variant := "default"

	// Check to see if the request is in the cache
	if c, exists := s.EndpointCache[EndpointIndex{url, method, variant}]; exists {
		return c, nil
	}

	file, e := ioutil.ReadFile(filepath.Join(s.RootDir, url, method, variant+".json"))

	if e != nil {
		return nil, e
	}

	ep := NewEndpoint()

	if e := json.Unmarshal(file, ep); e != nil {
		return nil, e
	}

{'fraction_non_alphanumeric': 0.29987883683360256, 'fraction_numerical': 0.0004038772213247173, 'mean_word_length': 1.8286693318103941, 'pattern_counts': {'":': 2, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '1100003', 'n_tokens_mistral': 1588, 'n_tokens_neox': 1512, 'n_words': 402}