<commit_before>// Copyright 2015 CoreOS, 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.

// The ec2 provider fetches a remote configuration from the ec2 user-data
// metadata service URL.

package ec2

import (
	"bufio"
	"bytes"
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"
	"time"

	"github.com/coreos/ignition/config"
	"github.com/coreos/ignition/src/log"
	"github.com/coreos/ignition/src/providers"
	"github.com/coreos/ignition/src/providers/util"
)

const (
	name           = "ec2"
	initialBackoff = 100 * time.Millisecond
	maxBackoff     = 30 * time.Second
	baseUrl        = "http://169.254.169.254/2009-04-04/"
	userdataUrl    = baseUrl + "user-data"
	metadataUrl    = baseUrl + "meta-data"
)

func init() {
	providers.Register(creator{})
}

type creator struct{}

func (creator) Name() string {
	return name
}

func (creator) Create(logger log.Logger) providers.Provider {
	return &provider{
		logger:  logger,
		backoff: initialBackoff,
		client:  &http.Client{},
	}
}

type provider struct {
	logger    log.Logger
	backoff   time.Duration
	client    *http.Client
	rawConfig []byte
}

func (provider) Name() string {
	return name
}

func (p provider) FetchConfig() (config.Config, error) {
	cfg, err := config.Parse(p.rawConfig)
	switch err {
	case config.ErrCloudConfig, config.ErrScript, config.ErrEmpty:
	default:
		return cfg, err
	}

	err = p.fetchSSHKeys(&cfg)

	return cfg, err
}

func (p *provider) IsOnline() bool {

	data, status, err := p.getData(userdataUrl)
	if err != nil {
		return false
	}

	switch status {
	case http.StatusOK, http.StatusNoContent:
		p.logger.Debug("config successfully fetched")
		p.rawConfig = data
	case http.StatusNotFound:
		p.logger.Debug("no config to fetch")
	default:
		p.logger.Debug("failed fetching: HTTP status: %s", http.StatusText(status))
		return false
	}

	return true
}

func (p provider) ShouldRetry() bool {
	return true
}

func (p *provider) BackoffDuration() time.Duration {
	return util.ExpBackoff(&p.backoff, maxBackoff)
}

// fetchSSHKeys fetches and appends ssh keys to the config.
func (p *provider) fetchSSHKeys(cfg *config.Config) error {
	keynames, err := p.getAttributes("/public-keys")
	if err != nil {
		return fmt.Errorf("error reading keys: %v", err)
	}

	keyIDs := make(map[string]string)
	for _, keyname := range keynames {
		tokens := strings.SplitN(keyname, "=", 2)
		if len(tokens) != 2 {
			return fmt.Errorf("malformed public key: %q", keyname)
		}
		keyIDs[tokens[1]] = tokens[0]
	}

	keys := []string{}
	for _, id := range keyIDs {
		sshkey, err := p.getAttribute("/public-keys/%s/openssh-key", id)
		if err != nil {
			return err
		}
		keys = append(keys, sshkey)
		p.logger.Info("found SSH public key for %q", id)
	}

	for i, user := range cfg.Passwd.Users {
		if user.Name == "core" {
			cfg.Passwd.Users[i].SSHAuthorizedKeys =
				append(cfg.Passwd.Users[i].SSHAuthorizedKeys,
					keys...)
			return nil
		}
	}

	cfg.Passwd.Users = append(cfg.Passwd.Users, config.User{
		Name:              "core",
		SSHAuthorizedKeys: keys,
	})

	return nil
}

// getData gets a url and reads the body.
func (p *provider) getData(url string) (data []byte, status int, err error) {
	err = p.logger.LogOp(func() error {
		resp, err := p.client.Get(url)
		if err != nil {
			return err
		}
		defer resp.Body.Close()

		status = resp.StatusCode
		data, err = ioutil.ReadAll(resp.Body)
		p.logger.Debug("got data %q", data)

		return err
	}, "GET %q", url)

	return
}

// getAttributes gets a list of metadata attributes from the format string.
func (p *provider) getAttributes(format string, a ...interface{}) ([]string, error) {
	path := fmt.Sprintf(format, a...)
	data, status, err := p.getData(metadataUrl + path)
	if err != nil {
		return nil, err
	}

	switch status {
	case http.StatusOK:
		scanner := bufio.NewScanner(bytes.NewBuffer(data))
		data := []string{}
		for scanner.Scan() {
			data = append(data, scanner.Text())
		}
		return data, scanner.Err()
	case http.StatusNotFound:
		return []string{}, nil
	default:
		return nil, fmt.Errorf("bad response: HTTP status code: %d", status)
	}
}

// getAttribute gets a singleton metadata attribute from the format string.
func (p *provider) getAttribute(format string, a ...interface{}) (string, error) {
	if data, err := p.getAttributes(format, a...); err == nil && len(data) > 0 {
		return data[0], nil
	} else {
		return "", err
	}
}
<commit_msg>providers/ec2: fix handling of configs to always fetch ssh keys.<commit_after>// Copyright 2015 CoreOS, 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.

// The ec2 provider fetches a remote configuration from the ec2 user-data
// metadata service URL.

package ec2

import (
	"bufio"
	"bytes"
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"
	"time"

	"github.com/coreos/ignition/config"
	"github.com/coreos/ignition/src/log"
	"github.com/coreos/ignition/src/providers"
	"github.com/coreos/ignition/src/providers/util"
)

const (
	name           = "ec2"
	initialBackoff = 100 * time.Millisecond
	maxBackoff     = 30 * time.Second
	baseUrl        = "http://169.254.169.254/2009-04-04/"
	userdataUrl    = baseUrl + "user-data"
	metadataUrl    = baseUrl + "meta-data"
)

func init() {
	providers.Register(creator{})
}

type creator struct{}

func (creator) Name() string {
	return name
}

func (creator) Create(logger log.Logger) providers.Provider {
	return &provider{
		logger:  logger,
		backoff: initialBackoff,
		client:  &http.Client{},
	}
}

type provider struct {
	logger    log.Logger
	backoff   time.Duration
	client    *http.Client
	rawConfig []byte
}

func (provider) Name() string {
	return name
}

func (p provider) FetchConfig() (config.Config, error) {
	cfg, err := config.Parse(p.rawConfig)
	if err == nil || err == config.ErrEmpty {
		err = p.fetchSSHKeys(&cfg)
	}

	return cfg, err
}

func (p *provider) IsOnline() bool {

	data, status, err := p.getData(userdataUrl)
	if err != nil {
		return false
	}

	switch status {
	case http.StatusOK, http.StatusNoContent:
		p.logger.Debug("config successfully fetched")
		p.rawConfig = data
	case http.StatusNotFound:
		p.logger.Debug("no config to fetch")
	default:
		p.logger.Debug("failed fetching: HTTP status: %s", http.StatusText(status))
		return false
	}

	return true
}

func (p provider) ShouldRetry() bool {
	return true
}

func (p *provider) BackoffDuration() time.Duration {
	return util.ExpBackoff(&p.backoff, maxBackoff)
}

// fetchSSHKeys fetches and appends ssh keys to the config.
func (p *provider) fetchSSHKeys(cfg *config.Config) error {
	keynames, err := p.getAttributes("/public-keys")
	if err != nil {
		return fmt.Errorf("error reading keys: %v", err)
	}

	keyIDs := make(map[string]string)
	for _, keyname := range keynames {
		tokens := strings.SplitN(keyname, "=", 2)
		if len(tokens) != 2 {
			return fmt.Errorf("malformed public key: %q", keyname)
		}
		keyIDs[tokens[1]] = tokens[0]
	}

	keys := []string{}
	for _, id := range keyIDs {
		sshkey, err := p.getAttribute("/public-keys/%s/openssh-key", id)
		if err != nil {
			return err
		}
		keys = append(keys, sshkey)
		p.logger.Info("found SSH public key for %q", id)
	}

	for i, user := range cfg.Passwd.Users {
		if user.Name == "core" {
			cfg.Passwd.Users[i].SSHAuthorizedKeys =
				append(cfg.Passwd.Users[i].SSHAuthorizedKeys,
					keys...)
			return nil
		}
	}

	cfg.Passwd.Users = append(cfg.Passwd.Users, config.User{
		Name:              "core",
		SSHAuthorizedKeys: keys,
	})

	return nil
}

// getData gets a url and reads the body.
func (p *provider) getData(url string) (data []byte, status int, err error) {
	err = p.logger.LogOp(func() error {
		resp, err := p.client.Get(url)
		if err != nil {
			return err
		}
		defer resp.Body.Close()

		status = resp.StatusCode
		data, err = ioutil.ReadAll(resp.Body)
		p.logger.Debug("got data %q", data)

		return err
	}, "GET %q", url)

	return
}

// getAttributes gets a list of metadata attributes from the format string.
func (p *provider) getAttributes(format string, a ...interface{}) ([]string, error) {
	path := fmt.Sprintf(format, a...)
	data, status, err := p.getData(metadataUrl + path)
	if err != nil {
		return nil, err
	}

	switch status {
	case http.StatusOK:
		scanner := bufio.NewScanner(bytes.NewBuffer(data))
		data := []string{}
		for scanner.Scan() {
			data = append(data, scanner.Text())
		}
		return data, scanner.Err()
	case http.StatusNotFound:
		return []string{}, nil
	default:
		return nil, fmt.Errorf("bad response: HTTP status code: %d", status)
	}
}

// getAttribute gets a singleton metadata attribute from the format string.
func (p *provider) getAttribute(format string, a ...interface{}) (string, error) {
	if data, err := p.getAttributes(format, a...); err == nil && len(data) > 0 {
		return data[0], nil
	} else {
		return "", err
	}
}
<|endoftext|>


<commit_before>package cleanhttp

import (
	"net/http"
	"strings"
	"unicode"
)

// HandlerInput provides input options to cleanhttp's handlers
type HandlerInput struct {
	ErrStatus int
}

// PrintablePathCheckHandler is a middleware that ensures the request path
// contains only printable runes.
func PrintablePathCheckHandler(next http.Handler, input *HandlerInput) http.Handler {
	if input == nil {
		input = &HandlerInput{
			ErrStatus: http.StatusBadRequest,
		}
	}

	// Default to http.StatusBadRequest on error
	if input.ErrStatus == 0 {
		input.ErrStatus = http.StatusBadRequest
	}

	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// Nil-check on input to make it optional
		// Check URL path for non-printable characters
		idx := strings.IndexFunc(r.URL.Path, func(c rune) bool {
			return !unicode.IsPrint(c)
		})

		if idx != -1 {
			w.WriteHeader(input.ErrStatus)
			return
		}

		next.ServeHTTP(w, r)
		return
	})
}
<commit_msg>Update input comment<commit_after>package cleanhttp

import (
	"net/http"
	"strings"
	"unicode"
)

// HandlerInput provides input options to cleanhttp's handlers
type HandlerInput struct {
	ErrStatus int
}

// PrintablePathCheckHandler is a middleware that ensures the request path
// contains only printable runes.
func PrintablePathCheckHandler(next http.Handler, input *HandlerInput) http.Handler {
	// Nil-check on input to make it optional
	if input == nil {
		input = &HandlerInput{
			ErrStatus: http.StatusBadRequest,
		}
	}

	// Default to http.StatusBadRequest on error
	if input.ErrStatus == 0 {
		input.ErrStatus = http.StatusBadRequest
	}

	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// Check URL path for non-printable characters
		idx := strings.IndexFunc(r.URL.Path, func(c rune) bool {
			return !unicode.IsPrint(c)
		})

		if idx != -1 {
			w.WriteHeader(input.ErrStatus)
			return
		}

		next.ServeHTTP(w, r)
		return
	})
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 Mark Samman <https://github.com/marksamman/golinkshortener>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package main

import (
	"fmt"
	"math/rand"
	"net"
	"net/http"
	"time"
)

type Click struct{}

type ShortenedTemplateData struct {
	Host   string
	LinkId string
	URL    string
	Clicks []Click
}

func shortenHandler(w http.ResponseWriter, req *http.Request) {
	if req.Method != "POST" {
		http.Error(w, "method must be POST", 500)
		return
	}

	ip, _, err := net.SplitHostPort(req.RemoteAddr)
	if err != nil {
		http.Error(w, "failed to split host/port", 500)
		return
	}

	randValue := rand.Intn(4096)
	randomString := []byte{urlSafe[randValue>>6], urlSafe[randValue&63]}

	var linkId int
	if err := db.QueryRow("INSERT INTO links (url, creator_ip, created, random) VALUES ($1, $2, $3, $4) RETURNING id", req.FormValue("url"), ip, time.Now().Unix(), randomString).Scan(&linkId); err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	http.Redirect(w, req, fmt.Sprintf("/shortened/%s%s", encodeInt(linkId), randomString), 302)
}

func shortenedHandler(w http.ResponseWriter, req *http.Request) {
	linkId := req.URL.Path[11:]
	if len(linkId) < 3 {
		http.NotFound(w, req)
		return
	}

	ip, _, err := net.SplitHostPort(req.RemoteAddr)
	if err != nil {
		http.Error(w, "failed to split host/port", 500)
		return
	}

	id := decodeInt(linkId[:len(linkId)-2])
	if id == 0 {
		http.NotFound(w, req)
		return
	}

	var url, creator_ip, random string
	if err := db.QueryRow("SELECT url, host(creator_ip), random FROM links WHERE id = $1::integer", id).Scan(&url, &creator_ip, &random); err != nil {
		http.NotFound(w, req)
		return
	}

	if random != linkId[len(linkId)-2:] {
		http.NotFound(w, req)
		return
	}

	if creator_ip != ip {
		http.Error(w, "forbidden", 403)
		return
	}

	if err := shortenedTemplate.Execute(w, ShortenedTemplateData{req.Host, linkId, url, []Click{}}); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

func rootHandler(w http.ResponseWriter, req *http.Request) {
	linkId := req.URL.Path[1:]
	if len(linkId) == 0 {
		http.ServeFile(w, req, "public/index.html")
		return
	}

	if len(linkId) < 3 {
		http.NotFound(w, req)
		return
	}

	conn := redisPool.Get()
	defer conn.Close()
	if res, _ := conn.Do("GET", linkId); res != nil {
		http.Redirect(w, req, string(res.([]uint8)), 301)
		conn.Do("EXPIRE", linkId, 10)
		return
	}

	id := decodeInt(linkId[:len(linkId)-2])
	if id == 0 {
		http.NotFound(w, req)
		return
	}

	var url, random string
	if err := db.QueryRow("SELECT url, random FROM links WHERE id = $1::integer", id).Scan(&url, &random); err != nil {
		http.NotFound(w, req)
		return
	}

	if random != linkId[len(linkId)-2:] {
		http.NotFound(w, req)
		return
	}

	http.Redirect(w, req, url, 301)
	if _, err := conn.Do("SET", linkId, url); err != nil {
		conn.Do("EXPIRE", linkId, 10)
	}
}
<commit_msg>Use constants from net/http for HTTP status codes<commit_after>/*
 * Copyright (c) 2014 Mark Samman <https://github.com/marksamman/golinkshortener>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package main

import (
	"fmt"
	"math/rand"
	"net"
	"net/http"
	"time"
)

type Click struct{}

type ShortenedTemplateData struct {
	Host   string
	LinkId string
	URL    string
	Clicks []Click
}

func shortenHandler(w http.ResponseWriter, req *http.Request) {
	if req.Method != "POST" {
		http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
		return
	}

	ip, _, err := net.SplitHostPort(req.RemoteAddr)
	if err != nil {
		http.Error(w, "failed to split host/port", http.StatusInternalServerError)
		return
	}

	randValue := rand.Intn(4096)
	randomString := []byte{urlSafe[randValue>>6], urlSafe[randValue&63]}

	var linkId int
	if err := db.QueryRow("INSERT INTO links (url, creator_ip, created, random) VALUES ($1, $2, $3, $4) RETURNING id", req.FormValue("url"), ip, time.Now().Unix(), randomString).Scan(&linkId); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	http.Redirect(w, req, fmt.Sprintf("/shortened/%s%s", encodeInt(linkId), randomString), http.StatusFound)
}

func shortenedHandler(w http.ResponseWriter, req *http.Request) {
	linkId := req.URL.Path[11:]
	if len(linkId) < 3 {
		http.NotFound(w, req)
		return
	}

	ip, _, err := net.SplitHostPort(req.RemoteAddr)
	if err != nil {
		http.Error(w, "failed to split host/port", http.StatusInternalServerError)
		return
	}

	id := decodeInt(linkId[:len(linkId)-2])
	if id == 0 {
		http.NotFound(w, req)
		return
	}

	var url, creator_ip, random string
	if err := db.QueryRow("SELECT url, host(creator_ip), random FROM links WHERE id = $1::integer", id).Scan(&url, &creator_ip, &random); err != nil {
		http.NotFound(w, req)
		return
	}

	if random != linkId[len(linkId)-2:] {
		http.NotFound(w, req)
		return
	}

	if creator_ip != ip {
		http.Error(w, "unauthorized", http.StatusUnauthorized)
		return
	}

	if err := shortenedTemplate.Execute(w, ShortenedTemplateData{req.Host, linkId, url, []Click{}}); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

func rootHandler(w http.ResponseWriter, req *http.Request) {
	linkId := req.URL.Path[1:]
	if len(linkId) == 0 {
		http.ServeFile(w, req, "public/index.html")
		return
	}

	if len(linkId) < 3 {
		http.NotFound(w, req)
		return
	}

	conn := redisPool.Get()
	defer conn.Close()
	if res, _ := conn.Do("GET", linkId); res != nil {
		http.Redirect(w, req, string(res.([]uint8)), http.StatusMovedPermanently)
		conn.Do("EXPIRE", linkId, 10)
		return
	}

	id := decodeInt(linkId[:len(linkId)-2])
	if id == 0 {
		http.NotFound(w, req)
		return
	}

	var url, random string
	if err := db.QueryRow("SELECT url, random FROM links WHERE id = $1::integer", id).Scan(&url, &random); err != nil {
		http.NotFound(w, req)
		return
	}

	if random != linkId[len(linkId)-2:] {
		http.NotFound(w, req)
		return
	}

	http.Redirect(w, req, url, http.StatusMovedPermanently)
	if _, err := conn.Do("SET", linkId, url); err != nil {
		conn.Do("EXPIRE", linkId, 10)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"sort"
	"strconv"
	"time"

	"github.com/gonum/stat"
	"github.com/pilu/traffic"
)

// PageData is used by the index template to populate things and stuff
type PageData struct {
	Machines   []string
	Sets       []int
	Start, End string
}

func handlerRoot(w traffic.ResponseWriter, r *traffic.Request) {
	s, e, err := db.getDataRange()
	if err != nil {
		log.Println(err)
	}

	s, _ = time.Parse(formatYYYYMMDD, "2015-10-10") // Because reasons.
	q := queryParams{
		Start:   s.Format(formatYYYYMMDD),
		End:     e.Format(formatYYYYMMDD),
		Machine: "all",
		Set:     0,
	}

	sets, err := db.getSetList(q)
	if err != nil {
		log.Println(err)
	}

	machines, err := db.getMachineList(q)
	if err != nil {
		log.Println(err)
	}

	w.Render("index", &PageData{machines, sets, q.Start, q.End})
}

func handlerResultsScatter3D(w traffic.ResponseWriter, r *traffic.Request) {
	w.WriteJSON(graphResultsRawScatter3D(db.getResults(params(r))))
}

func handlerResultsFreqDist(w traffic.ResponseWriter, r *traffic.Request) {
	w.WriteJSON(graphResultsFreqDist(db.getResults(params(r)), true, r.Param("type")))
}

func handlerMSFreqDist(w traffic.ResponseWriter, r *traffic.Request) {
	switch r.Param("type") {
	case "bubble":
		w.WriteJSON(graphMSFreqDistBubble(db.getMachineSetCombinations(params(r))))
	case "scatter3d":
		w.WriteJSON(graphMSFreqDistScatter3D(db.getMachineSetCombinations(params(r))))
	}
}

func handlerResultsTimeSeries(w traffic.ResponseWriter, r *traffic.Request) {
	w.WriteJSON(graphResultsTimeSeries(db.getResults(params(r)), true, r.Param("type")))
}

// NumbersData contains tidbits of information regarding numbers
type NumbersData struct {
	Frequent []int     `json:"frequent"`
	Least    []int     `json:"least"`
	Ranges   []string  `json:"ranges"`
	MeanAvg  []int     `json:"meanAvg"`
	ModeAvg  []float64 `json:"modeAvg"`
	Random   []int     `json:"random"`
}

type numFreq struct {
	num  int
	freq int
}

type ballSortByFreq []numFreq

func (b ballSortByFreq) Len() int           { return len(b) }
func (b ballSortByFreq) Swap(i, j int)      { b[i], b[j] = b[j], b[i] }
func (b ballSortByFreq) Less(i, j int) bool { return b[i].freq < b[j].freq }

func handlerNumbers(w traffic.ResponseWriter, r *traffic.Request) {
	p := params(r)
	resAvg, err := db.getResultsAverage(p)
	if err != nil {
		w.WriteJSON(err.Error())
		return
	}

	resRange, err := db.getResultsAverageRanges(p)
	if err != nil {
		w.WriteJSON(err.Error())
		return
	}

	// Treat the bonus ball as a separate entity as it is selected in isolation from
	// the first six. Hence bSort and bbSort.
	var (
		bSort               = make(ballSortByFreq, maxBallNum+1)
		bbSort              = make(ballSortByFreq, maxBallNum+1)
		modes               = make([][]float64, balls)
		mostFreq, leastFreq []int
	)
	for row := range db.getResults(p) {
		for ball := 0; ball < balls; ball++ {
			n := row.Num[ball]
			if ball < 6 {
				// Collate total frequncies for first 6
				bSort[n].num = n
				bSort[n].freq++
			} else {
				// Collate frequencies for bonus ball separately
				bbSort[n].num = n
				bbSort[n].freq++
			}
			// Collate raw numbers for mode
			modes[ball] = append(modes[ball], float64(n))
		}

	}

	// Sort both lists
	sort.Sort(sort.Reverse(bSort))
	sort.Sort(bbSort)

	// Pick out most frequent first 6
	for _, b := range bSort[:6] {
		mostFreq = append(mostFreq, b.num)
	}

	// Pick out least frequent last six, ignoring any 0s
	for i := len(bSort) - 1; i > 0; i-- {
		if len(leastFreq) == 6 {
			break
		}
		if bSort[i].num != 0 {
			leastFreq = append(leastFreq, bSort[i].num)
		}
	}

	// Sort the results, this is largely cosmetic.
	sort.Ints(mostFreq)
	sort.Ints(leastFreq)

	// Add the bonus ball for most frequent, don't duplicate numbers
	for i := len(bbSort) - 1; i > 0; i-- {
		if bbSort[i].num != 0 && !containsInt(mostFreq, bbSort[i].num) {
			mostFreq = append(mostFreq, bbSort[i].num)
			break
		}
	}

	// Add the bonus ball for least frequent, skipping any 0's and
	// ensuring no duplicate numbers
	for _, b := range bbSort {
		if b.num != 0 && !containsInt(leastFreq, b.num) {
			leastFreq = append(leastFreq, b.num)
			break
		}
	}

	m := make([]float64, balls)
	for i, set := range modes {
		m[i], _ = stat.Mode(set, nil)
	}

	w.WriteJSON(NumbersData{
		MeanAvg:  resAvg,
		ModeAvg:  m,
		Ranges:   resRange,
		Frequent: mostFreq,
		Least:    leastFreq,
		Random:   drawRandomSet(),
	})

}

func containsInt(a []int, t int) bool {
	for _, n := range a {
		if n == t {
			return true
		}
	}

	return false
}

func handlerListSets(w traffic.ResponseWriter, r *traffic.Request) {
	res, err := db.getSetList(params(r))
	if err != nil {
		w.WriteJSON(err)
	} else {
		w.WriteJSON(res)
	}
}

func handlerListMachines(w traffic.ResponseWriter, r *traffic.Request) {
	res, err := db.getMachineList(params(r))
	if err != nil {
		w.WriteJSON(err)
	} else {
		w.WriteJSON(res)
	}
}

func handlerDataRange(w traffic.ResponseWriter, r *traffic.Request) {
	f, l, err := db.getDataRange()
	if err != nil {
		log.Println("handlerDataRange:", err.Error())
	}

	w.WriteJSON(map[string]int64{"first": f.Unix(), "last": l.Unix()})
}

func params(r *traffic.Request) queryParams {
	set, _ := strconv.Atoi(r.Param("set"))
	return queryParams{
		Start:   r.Param("start"),
		End:     r.Param("end"),
		Set:     set,
		Machine: r.Param("machine"),
	}
}
<commit_msg>better commenting of numbers handler<commit_after>package main

import (
	"log"
	"sort"
	"strconv"
	"time"

	"github.com/gonum/stat"
	"github.com/pilu/traffic"
)

// PageData is used by the index template to populate things and stuff
type PageData struct {
	Machines   []string
	Sets       []int
	Start, End string
}

func handlerRoot(w traffic.ResponseWriter, r *traffic.Request) {
	s, e, err := db.getDataRange()
	if err != nil {
		log.Println(err)
	}

	s, _ = time.Parse(formatYYYYMMDD, "2015-10-10") // Because reasons.
	q := queryParams{
		Start:   s.Format(formatYYYYMMDD),
		End:     e.Format(formatYYYYMMDD),
		Machine: "all",
		Set:     0,
	}

	sets, err := db.getSetList(q)
	if err != nil {
		log.Println(err)
	}

	machines, err := db.getMachineList(q)
	if err != nil {
		log.Println(err)
	}

	w.Render("index", &PageData{machines, sets, q.Start, q.End})
}

func handlerResultsScatter3D(w traffic.ResponseWriter, r *traffic.Request) {
	w.WriteJSON(graphResultsRawScatter3D(db.getResults(params(r))))
}

func handlerResultsFreqDist(w traffic.ResponseWriter, r *traffic.Request) {
	w.WriteJSON(graphResultsFreqDist(db.getResults(params(r)), true, r.Param("type")))
}

func handlerMSFreqDist(w traffic.ResponseWriter, r *traffic.Request) {
	switch r.Param("type") {
	case "bubble":
		w.WriteJSON(graphMSFreqDistBubble(db.getMachineSetCombinations(params(r))))
	case "scatter3d":
		w.WriteJSON(graphMSFreqDistScatter3D(db.getMachineSetCombinations(params(r))))
	}
}

func handlerResultsTimeSeries(w traffic.ResponseWriter, r *traffic.Request) {
	w.WriteJSON(graphResultsTimeSeries(db.getResults(params(r)), true, r.Param("type")))
}

// NumbersData contains tidbits of information regarding numbers
type NumbersData struct {
	Frequent []int     `json:"frequent"`
	Least    []int     `json:"least"`
	Ranges   []string  `json:"ranges"`
	MeanAvg  []int     `json:"meanAvg"`
	ModeAvg  []float64 `json:"modeAvg"`
	Random   []int     `json:"random"`
}

type numFreq struct {
	num  int
	freq int
}

type ballSortByFreq []numFreq

func (b ballSortByFreq) Len() int           { return len(b) }
func (b ballSortByFreq) Swap(i, j int)      { b[i], b[j] = b[j], b[i] }
func (b ballSortByFreq) Less(i, j int) bool { return b[i].freq < b[j].freq }

func handlerNumbers(w traffic.ResponseWriter, r *traffic.Request) {
	p := params(r)
	resAvg, err := db.getResultsAverage(p)
	if err != nil {
		w.WriteJSON(err.Error())
		return
	}

	resRange, err := db.getResultsAverageRanges(p)
	if err != nil {
		w.WriteJSON(err.Error())
		return
	}

	// Treat the bonus ball as a separate entity as it is selected in isolation from
	// the first six. Hence bSort and bbSort.
	var (
		bSort               = make(ballSortByFreq, maxBallNum+1)
		bbSort              = make(ballSortByFreq, maxBallNum+1)
		modes               = make([][]float64, balls)
		mostFreq, leastFreq []int
	)
	for row := range db.getResults(p) {
		for ball := 0; ball < balls; ball++ {
			n := row.Num[ball]
			if ball < 6 {
				// Collate total frequncies for first 6
				bSort[n].num = n
				bSort[n].freq++
			} else {
				// Collate frequencies for bonus ball separately
				bbSort[n].num = n
				bbSort[n].freq++
			}
			// Collate raw numbers for mode
			modes[ball] = append(modes[ball], float64(n))
		}

	}

	// Sort both lists
	sort.Sort(sort.Reverse(bSort))
	sort.Sort(bbSort)

	// Pick out most frequent first 6
	for _, b := range bSort[:6] {
		mostFreq = append(mostFreq, b.num)
	}

	// Pick out least frequent last six, ignoring any 0s
	for i := len(bSort) - 1; i > 0; i-- {
		if len(leastFreq) == 6 {
			break
		}
		if bSort[i].num != 0 {
			leastFreq = append(leastFreq, bSort[i].num)
		}
	}

	// Sort the results, this is largely cosmetic.
	sort.Ints(mostFreq)
	sort.Ints(leastFreq)

	// Add the bonus ball for most frequent, don't duplicate numbers
	for i := len(bbSort) - 1; i > 0; i-- {
		if bbSort[i].num != 0 && !containsInt(mostFreq, bbSort[i].num) {
			mostFreq = append(mostFreq, bbSort[i].num)
			break
		}
	}

	// Add the bonus ball for least frequent, ensuring no duplicate numbers
	for _, b := range bbSort {
		if b.num != 0 && !containsInt(leastFreq, b.num) {
			leastFreq = append(leastFreq, b.num)
			break
		}
	}

	// Create Mode sets
	m := make([]float64, balls)
	for i, set := range modes {
		m[i], _ = stat.Mode(set, nil)
	}

	w.WriteJSON(NumbersData{
		MeanAvg:  resAvg,
		ModeAvg:  m,
		Ranges:   resRange,
		Frequent: mostFreq,
		Least:    leastFreq,
		Random:   drawRandomSet(),
	})

}

func containsInt(a []int, t int) bool {
	for _, n := range a {
		if n == t {
			return true
		}
	}

	return false
}

func handlerListSets(w traffic.ResponseWriter, r *traffic.Request) {
	res, err := db.getSetList(params(r))
	if err != nil {
		w.WriteJSON(err)
	} else {
		w.WriteJSON(res)
	}
}

func handlerListMachines(w traffic.ResponseWriter, r *traffic.Request) {
	res, err := db.getMachineList(params(r))
	if err != nil {
		w.WriteJSON(err)
	} else {
		w.WriteJSON(res)
	}
}

func handlerDataRange(w traffic.ResponseWriter, r *traffic.Request) {
	f, l, err := db.getDataRange()
	if err != nil {
		log.Println("handlerDataRange:", err.Error())
	}

	w.WriteJSON(map[string]int64{"first": f.Unix(), "last": l.Unix()})
}

func params(r *traffic.Request) queryParams {
	set, _ := strconv.Atoi(r.Param("set"))
	return queryParams{
		Start:   r.Param("start"),
		End:     r.Param("end"),
		Set:     set,
		Machine: r.Param("machine"),
	}
}
<|endoftext|>


<commit_before>// Copyright 2013 The Gorilla Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package handlers

import (
	"bufio"
	"fmt"
	"io"
	"net"
	"net/http"
	"net/url"
	"sort"
	"strconv"
	"strings"
	"time"
	"unicode/utf8"
)

// MethodHandler is an http.Handler that dispatches to a handler whose key in the MethodHandler's
// map matches the name of the HTTP request's method, eg: GET
//
// If the request's method is OPTIONS and OPTIONS is not a key in the map then the handler
// responds with a status of 200 and sets the Allow header to a comma-separated list of
// available methods.
//
// If the request's method doesn't match any of its keys the handler responds with
// a status of 405, Method not allowed and sets the Allow header to a comma-separated list
// of available methods.
type MethodHandler map[string]http.Handler

func (h MethodHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	if handler, ok := h[req.Method]; ok {
		handler.ServeHTTP(w, req)
	} else {
		allow := []string{}
		for k := range h {
			allow = append(allow, k)
		}
		sort.Strings(allow)
		w.Header().Set("Allow", strings.Join(allow, ", "))
		if req.Method == "OPTIONS" {
			w.WriteHeader(http.StatusOK)
		} else {
			http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		}
	}
}

// loggingHandler is the http.Handler implementation for LoggingHandlerTo and its friends
type loggingHandler struct {
	writer  io.Writer
	handler http.Handler
}

// combinedLoggingHandler is the http.Handler implementation for LoggingHandlerTo and its friends
type combinedLoggingHandler struct {
	writer  io.Writer
	handler http.Handler
}

func (h loggingHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	t := time.Now()
	var logger loggingResponseWriter
	if _, ok := w.(http.Hijacker); ok {
		logger = &hijackLogger{responseLogger: responseLogger{w: w}}
	} else {
		logger = &responseLogger{w: w}
	}
	url := *req.URL
	h.handler.ServeHTTP(logger, req)
	writeLog(h.writer, req, url, t, logger.Status(), logger.Size())
}

func (h combinedLoggingHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	t := time.Now()
	var logger loggingResponseWriter
	if _, ok := w.(http.Hijacker); ok {
		logger = &hijackLogger{responseLogger: responseLogger{w: w}}
	} else {
		logger = &responseLogger{w: w}
	}
	url := *req.URL
	h.handler.ServeHTTP(logger, req)
	writeCombinedLog(h.writer, req, url, t, logger.Status(), logger.Size())
}

type loggingResponseWriter interface {
	http.ResponseWriter
	Status() int
	Size() int
}

// responseLogger is wrapper of http.ResponseWriter that keeps track of its HTTP status
// code and body size
type responseLogger struct {
	w      http.ResponseWriter
	status int
	size   int
}

func (l *responseLogger) Header() http.Header {
	return l.w.Header()
}

func (l *responseLogger) Write(b []byte) (int, error) {
	if l.status == 0 {
		// The status will be StatusOK if WriteHeader has not been called yet
		l.status = http.StatusOK
	}
	size, err := l.w.Write(b)
	l.size += size
	return size, err
}

func (l *responseLogger) WriteHeader(s int) {
	l.w.WriteHeader(s)
	l.status = s
}

func (l *responseLogger) Status() int {
	return l.status
}

func (l *responseLogger) Size() int {
	return l.size
}

type hijackLogger struct {
	responseLogger
}

func (l *hijackLogger) Hijack() (net.Conn, *bufio.ReadWriter, error) {
	h := l.responseLogger.w.(http.Hijacker)
	conn, rw, err := h.Hijack()
	if err == nil && l.responseLogger.status == 0 {
		// The status will be StatusSwitchingProtocols if there was no error and WriteHeader has not been called yet
		l.responseLogger.status = http.StatusSwitchingProtocols
	}
	return conn, rw, err
}

const lowerhex = "0123456789abcdef"

func appendQuoted(buf []byte, s string) []byte {
	var runeTmp [utf8.UTFMax]byte
	for width := 0; len(s) > 0; s = s[width:] {
		r := rune(s[0])
		width = 1
		if r >= utf8.RuneSelf {
			r, width = utf8.DecodeRuneInString(s)
		}
		if width == 1 && r == utf8.RuneError {
			buf = append(buf, `\x`...)
			buf = append(buf, lowerhex[s[0]>>4])
			buf = append(buf, lowerhex[s[0]&0xF])
			continue
		}
		if r == rune('"') || r == '\\' { // always backslashed
			buf = append(buf, '\\')
			buf = append(buf, byte(r))
			continue
		}
		if strconv.IsPrint(r) {
			n := utf8.EncodeRune(runeTmp[:], r)
			buf = append(buf, runeTmp[:n]...)
			continue
		}
		switch r {
		case '\a':
			buf = append(buf, `\a`...)
		case '\b':
			buf = append(buf, `\b`...)
		case '\f':
			buf = append(buf, `\f`...)
		case '\n':
			buf = append(buf, `\n`...)
		case '\r':
			buf = append(buf, `\r`...)
		case '\t':
			buf = append(buf, `\t`...)
		case '\v':
			buf = append(buf, `\v`...)
		default:
			switch {
			case r < ' ':
				buf = append(buf, `\x`...)
				buf = append(buf, lowerhex[s[0]>>4])
				buf = append(buf, lowerhex[s[0]&0xF])
			case r > utf8.MaxRune:
				r = 0xFFFD
				fallthrough
			case r < 0x10000:
				buf = append(buf, `\u`...)
				for s := 12; s >= 0; s -= 4 {
					buf = append(buf, lowerhex[r>>uint(s)&0xF])
				}
			default:
				buf = append(buf, `\U`...)
				for s := 28; s >= 0; s -= 4 {
					buf = append(buf, lowerhex[r>>uint(s)&0xF])
				}
			}
		}
	}
	return buf

}

// buildCommonLogLine builds a log entry for req in Apache Common Log Format.
// ts is the timestamp with which the entry should be logged.
// status and size are used to provide the response HTTP status and size.
func buildCommonLogLine(req *http.Request, url url.URL, ts time.Time, status int, size int) []byte {
	username := "-"
	if url.User != nil {
		if name := url.User.Username(); name != "" {
			username = name
		}
	}

	host, _, err := net.SplitHostPort(req.RemoteAddr)

	if err != nil {
		host = req.RemoteAddr
	}

	uri := url.RequestURI()

	buf := make([]byte, 0, 3*(len(host)+len(username)+len(req.Method)+len(uri)+len(req.Proto)+50)/2)
	buf = append(buf, host...)
	buf = append(buf, " - "...)
	buf = append(buf, username...)
	buf = append(buf, " ["...)
	buf = append(buf, ts.Format("02/Jan/2006:15:04:05 -0700")...)
	buf = append(buf, `] "`...)
	buf = append(buf, req.Method...)
	buf = append(buf, " "...)
	buf = appendQuoted(buf, uri)
	buf = append(buf, " "...)
	buf = append(buf, req.Proto...)
	buf = append(buf, `" `...)
	buf = append(buf, strconv.Itoa(status)...)
	buf = append(buf, " "...)
	buf = append(buf, strconv.Itoa(size)...)
	return buf
}

// writeLog writes a log entry for req to w in Apache Common Log Format.
// ts is the timestamp with which the entry should be logged.
// status and size are used to provide the response HTTP status and size.
func writeLog(w io.Writer, req *http.Request, url url.URL, ts time.Time, status, size int) {
	buf := buildCommonLogLine(req, url, ts, status, size)
	buf = append(buf, '\n')
	w.Write(buf)
}

// writeCombinedLog writes a log entry for req to w in Apache Combined Log Format.
// ts is the timestamp with which the entry should be logged.
// status and size are used to provide the response HTTP status and size.
func writeCombinedLog(w io.Writer, req *http.Request, url url.URL, ts time.Time, status, size int) {
	buf := buildCommonLogLine(req, url, ts, status, size)
	buf = append(buf, ` "`...)
	buf = appendQuoted(buf, req.Referer())
	buf = append(buf, `" "`...)
	buf = appendQuoted(buf, req.UserAgent())
	buf = append(buf, '"', '\n')
	w.Write(buf)
}

// CombinedLoggingHandler return a http.Handler that wraps h and logs requests to out in
// Apache Combined Log Format.
//
// See http://httpd.apache.org/docs/2.2/logs.html#combined for a description of this format.
//
// LoggingHandler always sets the ident field of the log to -
func CombinedLoggingHandler(out io.Writer, h http.Handler) http.Handler {
	return combinedLoggingHandler{out, h}
}

// LoggingHandler return a http.Handler that wraps h and logs requests to out in
// Apache Common Log Format (CLF).
//
// See http://httpd.apache.org/docs/2.2/logs.html#common for a description of this format.
//
// LoggingHandler always sets the ident field of the log to -
func LoggingHandler(out io.Writer, h http.Handler) http.Handler {
	return loggingHandler{out, h}
}

// isContentType validates the Content-Type header
// is contentType. That is, its type and subtype match.
func isContentType(h http.Header, contentType string) bool {
	ct := h.Get("Content-Type")
	if i := strings.IndexRune(ct, ';'); i != -1 {
		ct = ct[0:i]
	}
	return ct == contentType
}

// ContentTypeHandler wraps and returns a http.Handler, validating the request content type
// is acompatible with the contentTypes list.
// It writes a HTTP 415 error if that fails.
//
// Only PUT, POST, and PATCH requests are considered.
func ContentTypeHandler(h http.Handler, contentTypes ...string) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if !(r.Method == "PUT" || r.Method == "POST" || r.Method == "PATCH") {
			h.ServeHTTP(w, r)
			return
		}

		for _, ct := range contentTypes {
			if isContentType(r.Header, ct) {
				h.ServeHTTP(w, r)
				return
			}
		}
		http.Error(w, fmt.Sprintf("Unsupported content type %q; expected one of %q", r.Header.Get("Content-Type"), contentTypes), http.StatusUnsupportedMediaType)
	})
}

const (
	// HTTPMethodOverrideHeader is a commonly used
	// http header to override a request method.
	HTTPMethodOverrideHeader = "X-HTTP-Method-Override"
	// HTTPMethodOverrideFormKey is a commonly used
	// HTML form key to override a request method.
	HTTPMethodOverrideFormKey = "_method"
)

// HTTPMethodOverrideHandler wraps and returns a http.Handler which checks for the X-HTTP-Method-Override header
// or the _method form key, and overrides (if valid) request.Method with its value.
//
// This is especially useful for http clients that don't support many http verbs.
// It isn't secure to override e.g a GET to a POST, so only POST requests are considered.
// Likewise, the override method can only be a "write" method: PUT, PATCH or DELETE.
//
// Form method takes precedence over header method.
func HTTPMethodOverrideHandler(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.Method == "POST" {
			om := r.FormValue(HTTPMethodOverrideFormKey)
			if om == "" {
				om = r.Header.Get(HTTPMethodOverrideHeader)
			}
			if om == "PUT" || om == "PATCH" || om == "DELETE" {
				r.Method = om
			}
		}
		h.ServeHTTP(w, r)
	})
}
<commit_msg>support http.Flusher and http.CloseNotifier interfaces in logging http.ResponseWriter wrapper<commit_after>// Copyright 2013 The Gorilla Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package handlers

import (
	"bufio"
	"fmt"
	"io"
	"net"
	"net/http"
	"net/url"
	"sort"
	"strconv"
	"strings"
	"time"
	"unicode/utf8"
)

// MethodHandler is an http.Handler that dispatches to a handler whose key in the MethodHandler's
// map matches the name of the HTTP request's method, eg: GET
//
// If the request's method is OPTIONS and OPTIONS is not a key in the map then the handler
// responds with a status of 200 and sets the Allow header to a comma-separated list of
// available methods.
//
// If the request's method doesn't match any of its keys the handler responds with
// a status of 405, Method not allowed and sets the Allow header to a comma-separated list
// of available methods.
type MethodHandler map[string]http.Handler

func (h MethodHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	if handler, ok := h[req.Method]; ok {
		handler.ServeHTTP(w, req)
	} else {
		allow := []string{}
		for k := range h {
			allow = append(allow, k)
		}
		sort.Strings(allow)
		w.Header().Set("Allow", strings.Join(allow, ", "))
		if req.Method == "OPTIONS" {
			w.WriteHeader(http.StatusOK)
		} else {
			http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		}
	}
}

// loggingHandler is the http.Handler implementation for LoggingHandlerTo and its friends
type loggingHandler struct {
	writer  io.Writer
	handler http.Handler
}

// combinedLoggingHandler is the http.Handler implementation for LoggingHandlerTo and its friends
type combinedLoggingHandler struct {
	writer  io.Writer
	handler http.Handler
}

func (h loggingHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	t := time.Now()
	var logger loggingResponseWriter
	if _, ok := w.(http.Hijacker); ok {
		logger = &hijackLogger{responseLogger: responseLogger{w: w}}
	} else {
		logger = &responseLogger{w: w}
	}
	url := *req.URL
	h.handler.ServeHTTP(logger, req)
	writeLog(h.writer, req, url, t, logger.Status(), logger.Size())
}

func (h combinedLoggingHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	t := time.Now()
	logger := makeLogger(w)
	url := *req.URL
	h.handler.ServeHTTP(logger, req)
	writeCombinedLog(h.writer, req, url, t, logger.Status(), logger.Size())
}

func makeLogger(w http.ResponseWriter) loggingResponseWriter {
	var responseLogger = &responseLogger{w: w}
	var logger loggingResponseWriter = responseLogger
	if _, ok := w.(http.Hijacker); ok {
		logger = &hijackLogger{*responseLogger}
	}
	if _, ok := w.(http.Flusher); ok {
		logger = &flushLogger{logger}
	}
	if _, ok := w.(http.CloseNotifier); ok {
		logger = &closeNotifyLogger{logger}
	}
	return logger
}

type loggingResponseWriter interface {
	http.ResponseWriter
	Source() http.ResponseWriter
	Status() int
	Size() int
}

// responseLogger is wrapper of http.ResponseWriter that keeps track of its HTTP status
// code and body size
type responseLogger struct {
	w      http.ResponseWriter
	status int
	size   int
}

func (l *responseLogger) Header() http.Header {
	return l.w.Header()
}

func (l *responseLogger) Write(b []byte) (int, error) {
	if l.status == 0 {
		// The status will be StatusOK if WriteHeader has not been called yet
		l.status = http.StatusOK
	}
	size, err := l.w.Write(b)
	l.size += size
	return size, err
}

func (l *responseLogger) WriteHeader(s int) {
	l.w.WriteHeader(s)
	l.status = s
}

func (l *responseLogger) Source() http.ResponseWriter {
	return l.w
}

func (l *responseLogger) Status() int {
	return l.status
}

func (l *responseLogger) Size() int {
	return l.size
}

type hijackLogger struct {
	responseLogger
}

func (l *hijackLogger) Hijack() (net.Conn, *bufio.ReadWriter, error) {
	h := l.responseLogger.w.(http.Hijacker)
	conn, rw, err := h.Hijack()
	if err == nil && l.responseLogger.status == 0 {
		// The status will be StatusSwitchingProtocols if there was no error and WriteHeader has not been called yet
		l.responseLogger.status = http.StatusSwitchingProtocols
	}
	return conn, rw, err
}

type flushLogger struct {
	loggingResponseWriter
}

func (l *flushLogger) Flush() {
	f := l.Source().(http.Flusher)
	f.Flush()
}

type closeNotifyLogger struct {
	loggingResponseWriter
}

func (l *closeNotifyLogger) CloseNotify() <-chan bool {
	f := l.Source().(http.CloseNotifier)
	return f.CloseNotify()
}

const lowerhex = "0123456789abcdef"

func appendQuoted(buf []byte, s string) []byte {
	var runeTmp [utf8.UTFMax]byte
	for width := 0; len(s) > 0; s = s[width:] {
		r := rune(s[0])
		width = 1
		if r >= utf8.RuneSelf {
			r, width = utf8.DecodeRuneInString(s)
		}
		if width == 1 && r == utf8.RuneError {
			buf = append(buf, `\x`...)
			buf = append(buf, lowerhex[s[0]>>4])
			buf = append(buf, lowerhex[s[0]&0xF])
			continue
		}
		if r == rune('"') || r == '\\' { // always backslashed
			buf = append(buf, '\\')
			buf = append(buf, byte(r))
			continue
		}
		if strconv.IsPrint(r) {
			n := utf8.EncodeRune(runeTmp[:], r)
			buf = append(buf, runeTmp[:n]...)
			continue
		}
		switch r {
		case '\a':
			buf = append(buf, `\a`...)
		case '\b':
			buf = append(buf, `\b`...)
		case '\f':
			buf = append(buf, `\f`...)
		case '\n':
			buf = append(buf, `\n`...)
		case '\r':
			buf = append(buf, `\r`...)
		case '\t':
			buf = append(buf, `\t`...)
		case '\v':
			buf = append(buf, `\v`...)
		default:
			switch {
			case r < ' ':
				buf = append(buf, `\x`...)
				buf = append(buf, lowerhex[s[0]>>4])
				buf = append(buf, lowerhex[s[0]&0xF])
			case r > utf8.MaxRune:
				r = 0xFFFD
				fallthrough
			case r < 0x10000:
				buf = append(buf, `\u`...)
				for s := 12; s >= 0; s -= 4 {
					buf = append(buf, lowerhex[r>>uint(s)&0xF])
				}
			default:
				buf = append(buf, `\U`...)
				for s := 28; s >= 0; s -= 4 {
					buf = append(buf, lowerhex[r>>uint(s)&0xF])
				}
			}
		}
	}
	return buf

}

// buildCommonLogLine builds a log entry for req in Apache Common Log Format.
// ts is the timestamp with which the entry should be logged.
// status and size are used to provide the response HTTP status and size.
func buildCommonLogLine(req *http.Request, url url.URL, ts time.Time, status int, size int) []byte {
	username := "-"
	if url.User != nil {
		if name := url.User.Username(); name != "" {
			username = name
		}
	}

	host, _, err := net.SplitHostPort(req.RemoteAddr)

	if err != nil {
		host = req.RemoteAddr
	}

	uri := url.RequestURI()

	buf := make([]byte, 0, 3*(len(host)+len(username)+len(req.Method)+len(uri)+len(req.Proto)+50)/2)
	buf = append(buf, host...)
	buf = append(buf, " - "...)
	buf = append(buf, username...)
	buf = append(buf, " ["...)
	buf = append(buf, ts.Format("02/Jan/2006:15:04:05 -0700")...)
	buf = append(buf, `] "`...)
	buf = append(buf, req.Method...)
	buf = append(buf, " "...)
	buf = appendQuoted(buf, uri)
	buf = append(buf, " "...)
	buf = append(buf, req.Proto...)
	buf = append(buf, `" `...)
	buf = append(buf, strconv.Itoa(status)...)
	buf = append(buf, " "...)
	buf = append(buf, strconv.Itoa(size)...)
	return buf
}

// writeLog writes a log entry for req to w in Apache Common Log Format.
// ts is the timestamp with which the entry should be logged.
// status and size are used to provide the response HTTP status and size.
func writeLog(w io.Writer, req *http.Request, url url.URL, ts time.Time, status, size int) {
	buf := buildCommonLogLine(req, url, ts, status, size)
	buf = append(buf, '\n')
	w.Write(buf)
}

// writeCombinedLog writes a log entry for req to w in Apache Combined Log Format.
// ts is the timestamp with which the entry should be logged.
// status and size are used to provide the response HTTP status and size.
func writeCombinedLog(w io.Writer, req *http.Request, url url.URL, ts time.Time, status, size int) {
	buf := buildCommonLogLine(req, url, ts, status, size)
	buf = append(buf, ` "`...)
	buf = appendQuoted(buf, req.Referer())
	buf = append(buf, `" "`...)
	buf = appendQuoted(buf, req.UserAgent())
	buf = append(buf, '"', '\n')
	w.Write(buf)
}

// CombinedLoggingHandler return a http.Handler that wraps h and logs requests to out in
// Apache Combined Log Format.
//
// See http://httpd.apache.org/docs/2.2/logs.html#combined for a description of this format.
//
// LoggingHandler always sets the ident field of the log to -
func CombinedLoggingHandler(out io.Writer, h http.Handler) http.Handler {
	return combinedLoggingHandler{out, h}
}

// LoggingHandler return a http.Handler that wraps h and logs requests to out in
// Apache Common Log Format (CLF).
//
// See http://httpd.apache.org/docs/2.2/logs.html#common for a description of this format.
//
// LoggingHandler always sets the ident field of the log to -
func LoggingHandler(out io.Writer, h http.Handler) http.Handler {
	return loggingHandler{out, h}
}

// isContentType validates the Content-Type header
// is contentType. That is, its type and subtype match.
func isContentType(h http.Header, contentType string) bool {
	ct := h.Get("Content-Type")
	if i := strings.IndexRune(ct, ';'); i != -1 {
		ct = ct[0:i]
	}
	return ct == contentType
}

// ContentTypeHandler wraps and returns a http.Handler, validating the request content type
// is acompatible with the contentTypes list.
// It writes a HTTP 415 error if that fails.
//
// Only PUT, POST, and PATCH requests are considered.
func ContentTypeHandler(h http.Handler, contentTypes ...string) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if !(r.Method == "PUT" || r.Method == "POST" || r.Method == "PATCH") {
			h.ServeHTTP(w, r)
			return
		}

		for _, ct := range contentTypes {
			if isContentType(r.Header, ct) {
				h.ServeHTTP(w, r)
				return
			}
		}
		http.Error(w, fmt.Sprintf("Unsupported content type %q; expected one of %q", r.Header.Get("Content-Type"), contentTypes), http.StatusUnsupportedMediaType)
	})
}

const (
	// HTTPMethodOverrideHeader is a commonly used
	// http header to override a request method.
	HTTPMethodOverrideHeader = "X-HTTP-Method-Override"
	// HTTPMethodOverrideFormKey is a commonly used
	// HTML form key to override a request method.
	HTTPMethodOverrideFormKey = "_method"
)

// HTTPMethodOverrideHandler wraps and returns a http.Handler which checks for the X-HTTP-Method-Override header
// or the _method form key, and overrides (if valid) request.Method with its value.
//
// This is especially useful for http clients that don't support many http verbs.
// It isn't secure to override e.g a GET to a POST, so only POST requests are considered.
// Likewise, the override method can only be a "write" method: PUT, PATCH or DELETE.
//
// Form method takes precedence over header method.
func HTTPMethodOverrideHandler(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.Method == "POST" {
			om := r.FormValue(HTTPMethodOverrideFormKey)
			if om == "" {
				om = r.Header.Get(HTTPMethodOverrideHeader)
			}
			if om == "PUT" || om == "PATCH" || om == "DELETE" {
				r.Method = om
			}
		}
		h.ServeHTTP(w, r)
	})
}
<|endoftext|>


<commit_before>package main

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

	"github.com/gorilla/mux"
)

func Index(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusOK)
	fmt.Fprint(w, "Welcome!\n")
}

//handlers for municipality
func MunicipalIndex(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	var lat float64
	var lon float64
	var err error

	if lat, err =  strconv.ParseFloat(vars["lat"], 64); err != nil{
		panic(err)
	}
	if lon, err = strconv.ParseFloat(vars["lon"], 64); err != nil{
		panic(err)
	}

	m := RepoFindCourtByAddress(lat, lon)
	if m.Id > 0 {
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		w.WriteHeader(http.StatusOK)
		if err := json.NewEncoder(w).Encode(m); err != nil {
			panic(err)
		}
		return
	}

	// If we didn't find it, 404
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusNotFound)
	if err := json.NewEncoder(w).Encode(jsonErr{Code: http.StatusNotFound, Text: "Not Found"}); err != nil {
		panic(err)
	}
}

func MunicipalShow(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	var mId int
	var err error

	if mId, err = strconv.Atoi(vars["mId"]); err != nil {
		panic(err)
	}

	m := RepoFindMunicipality(mId)
	if m.Id > 0 {
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		w.WriteHeader(http.StatusOK)
		if err := json.NewEncoder(w).Encode(m); err != nil {
			panic(err)
		}
		return
	}

	// If we didn't find it, 404
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusNotFound)
	if err := json.NewEncoder(w).Encode(jsonErr{Code: http.StatusNotFound, Text: "Not Found"}); err != nil {
		panic(err)
	}
}

//handlers for court
func CourtIndex(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusOK)
	if err := json.NewEncoder(w).Encode(courts); err != nil {
		panic(err)
	}
}

func CourtCreate(w http.ResponseWriter, r *http.Request){

  var court Court
	var err error
  //Check if malicious user is trying to overload the server
  body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1048576))
  if err != nil{
    panic(err)
  }
  if err := r.Body.Close(); err != nil{
    panic(err)
  }
  if err := json.Unmarshal(body, &court); err != nil{
    w.Header().Set("Content-Type", "application/json; charset=UTF-8")

		w.WriteHeader(422) // unprocessable entity
		if err := json.NewEncoder(w).Encode(err); err != nil {
			panic(err)
		}

  }
  if court, err = RepoCreateCourt(court); err != nil {
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		w.WriteHeader(422) // unprocessable entity
		if err := json.NewEncoder(w).Encode(err); err != nil {
			panic(err)
		}
	}
  w.Header().Set("Content-Type", "application/json; charset=UTF-8")
  w.WriteHeader(http.StatusCreated)
  if err := json.NewEncoder(w).Encode(court); err != nil {
    panic(err)
  }
}

func CourtUpdate(w http.ResponseWriter, r *http.Request) {

	vars := mux.Vars(r)
	var courtId int
	var err error

	if courtId, err = strconv.Atoi(vars["courtId"]); err != nil {
		panic(err)
	}

	var court Court
	//Check if malicious user is trying to overload the server
	body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1048576))
	if err != nil {
		panic(err)
	}
	if err := r.Body.Close(); err != nil {
		panic(err)
	}
	if err := json.Unmarshal(body, &court); err != nil {
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		w.WriteHeader(422) // unprocessable entity
		if err := json.NewEncoder(w).Encode(err); err != nil {
			panic(err)
		}
	}

  if err := RepoUpdateCourt(&court, courtId); err != nil{
    w.Header().Set("Content-Type", "application/json; charset=UTF-8")
    w.WriteHeader(http.StatusNotFound) //TODO: Use right status code
    if err := json.NewEncoder(w).Encode(jsonErr{Code: http.StatusNotFound, Text: "Not Found"}); err != nil {
      panic(err)
    }
  }
  w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusOK) // TODO: Use right status code

	if err := json.NewEncoder(w).Encode(court); err != nil {
		panic(err)
	}
}

func CourtDelete(w http.ResponseWriter, r *http.Request){
	vars := mux.Vars(r)
  var courtId int
  var err error

  if courtId, err = strconv.Atoi(vars["courtId"]); err != nil{
    panic(err)
  }

	if err := RepoDeleteCourt(courtId); err!= nil {
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
    w.WriteHeader(http.StatusNotFound) //TODO: Use right status code
    if err := json.NewEncoder(w).Encode(jsonErr{Code: http.StatusNotFound, Text: "Not Found"}); err != nil {
      panic(err)
    }
	} else {
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
    w.WriteHeader(http.StatusOK)
		if err := json.NewEncoder(w).Encode(jsonErr{Code: http.StatusOK, Text: "Item Deleted"}); err != nil {
      panic(err)
    }
	}
}

func CourtShow(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	var courtId int
	var err error

	if courtId, err = strconv.Atoi(vars["courtId"]); err != nil {
		panic(err)
	}

	court := RepoFindCourt(courtId)
	if court.Id > 0 {
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		w.WriteHeader(http.StatusOK)
		if err := json.NewEncoder(w).Encode(court); err != nil {
			panic(err)
		}
		return
	}

	// If we didn't find it, 404
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusNotFound)
	if err := json.NewEncoder(w).Encode(jsonErr{Code: http.StatusNotFound, Text: "Not Found"}); err != nil {
		panic(err)
	}
}

//handlers for Ticket
func TicketIndex(w http.ResponseWriter, r *http.Request) {
	params := r.URL.Query()
	driver_licenses, ok := params["driver_license"]
	if ok {
		driver_license := string(driver_licenses[0])
		tic := RepoFindTicketByDriverLicenseNumber(driver_license)
		if tic.Validate() == nil {
			w.Header().Set("Content-Type", "application/json; charset=UTF-8")
			w.WriteHeader(http.StatusOK)
			if err := json.NewEncoder(w).Encode(tic); err != nil {
				panic(err)
			}
		}else {
			w.Header().Set("Content-Type", "application/json; charset=UTF-8")
			w.WriteHeader(http.StatusNotFound)
			if err := json.NewEncoder(w).Encode(jsonErr{Code: http.StatusNotFound, Text: "Not Found"}); err != nil {
				panic(err)
			}
		}
	} else {
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		w.WriteHeader(http.StatusOK)
		if err := json.NewEncoder(w).Encode(gTickets); err != nil {
			panic(err)
		}
	}
}

func TicketCreate(w http.ResponseWriter, r *http.Request){

  var ticket Ticket
	var err error
  //Check if malicious user is trying to overload the server
  body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1048576))
  if err != nil{
    panic(err)
  }
  if err := r.Body.Close(); err != nil{
    panic(err)
  }
  if err := json.Unmarshal(body, &ticket); err != nil{
    w.Header().Set("Content-Type", "application/json; charset=UTF-8")

		w.WriteHeader(422) // unprocessable entity
		if err := json.NewEncoder(w).Encode(err); err != nil {
			panic(err)
		}

  }
  if ticket, err = RepoCreateTicket(ticket); err != nil {
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		w.WriteHeader(422) // unprocessable entity
		if err := json.NewEncoder(w).Encode(err); err != nil {
			panic(err)
		}
	}
  w.Header().Set("Content-Type", "application/json; charset=UTF-8")
  w.WriteHeader(http.StatusCreated)
  if err := json.NewEncoder(w).Encode(ticket); err != nil {
    panic(err)
  }
}

func TicketUpdate(w http.ResponseWriter, r *http.Request) {

	vars := mux.Vars(r)
	var ticketId int
	var err error

	if ticketId, err = strconv.Atoi(vars["ticketId"]); err != nil {
		panic(err)
	}

	var ticket Ticket
	//Check if malicious user is trying to overload the server
	body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1048576))
	if err != nil {
		panic(err)
	}
	if err := r.Body.Close(); err != nil {
		panic(err)
	}
	if err := json.Unmarshal(body, &ticket); err != nil {
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		w.WriteHeader(422) // unprocessable entity
		if err := json.NewEncoder(w).Encode(err); err != nil {
			panic(err)
		}
	}

  if err := RepoUpdateTicket(&ticket, ticketId); err != nil{
    w.Header().Set("Content-Type", "application/json; charset=UTF-8")
    w.WriteHeader(http.StatusNotFound) //TODO: Use right status code
    if err := json.NewEncoder(w).Encode(jsonErr{Code: http.StatusNotFound, Text: "Not Found"}); err != nil {
      panic(err)
    }
  }
  w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusOK) // TODO: Use right status code

	if err := json.NewEncoder(w).Encode(ticket); err != nil {
		panic(err)
	}
}

func TicketDelete(w http.ResponseWriter, r *http.Request){
	vars := mux.Vars(r)
  var ticketId int
  var err error

  if ticketId, err = strconv.Atoi(vars["ticketId"]); err != nil{
    panic(err)
  }

	if err := RepoDeleteTicket(ticketId); err!= nil {
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
    w.WriteHeader(http.StatusNotFound) //TODO: Use right status code
    if err := json.NewEncoder(w).Encode(jsonErr{Code: http.StatusNotFound, Text: "Not Found"}); err != nil {
      panic(err)
    }
	} else {
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
    w.WriteHeader(http.StatusOK)
		if err := json.NewEncoder(w).Encode(jsonErr{Code: http.StatusOK, Text: "Item Deleted"}); err != nil {
      panic(err)
    }
	}
}

func TicketShow(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	var ticketId int
	var err error

	if ticketId, err = strconv.Atoi(vars["ticketId"]); err != nil {
		panic(err)
	}

	ticket := RepoFindTicket(ticketId)
	if ticket.Id > 0 {
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		w.WriteHeader(http.StatusOK)
		if err := json.NewEncoder(w).Encode(ticket); err != nil {
			panic(err)
		}
		return
	}

	// If we didn't find it, 404
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusNotFound)
	if err := json.NewEncoder(w).Encode(jsonErr{Code: http.StatusNotFound, Text: "Not Found"}); err != nil {
		panic(err)
	}
}

/*
Example of JSON data structure
{
  "id":"1",
  "key":"value",
  "key2":["value1","value2"]
}
*/

/*
Test with this curl command:
curl -H "Content-Type: application/json" -d '{"name":"New Todo"}' http://localhost:8080/todos
*/
<commit_msg>Fixed ticket not found logic<commit_after>package main

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

	"github.com/gorilla/mux"
)

func Index(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusOK)
	fmt.Fprint(w, "Welcome!\n")
}

//handlers for municipality
func MunicipalIndex(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	var lat float64
	var lon float64
	var err error

	if lat, err =  strconv.ParseFloat(vars["lat"], 64); err != nil{
		panic(err)
	}
	if lon, err = strconv.ParseFloat(vars["lon"], 64); err != nil{
		panic(err)
	}

	m := RepoFindCourtByAddress(lat, lon)
	if m.Id > 0 {
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		w.WriteHeader(http.StatusOK)
		if err := json.NewEncoder(w).Encode(m); err != nil {
			panic(err)
		}
		return
	}

	// If we didn't find it, 404
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusNotFound)
	if err := json.NewEncoder(w).Encode(jsonErr{Code: http.StatusNotFound, Text: "Not Found"}); err != nil {
		panic(err)
	}
}

func MunicipalShow(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	var mId int
	var err error

	if mId, err = strconv.Atoi(vars["mId"]); err != nil {
		panic(err)
	}

	m := RepoFindMunicipality(mId)
	if m.Id > 0 {
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		w.WriteHeader(http.StatusOK)
		if err := json.NewEncoder(w).Encode(m); err != nil {
			panic(err)
		}
		return
	}

	// If we didn't find it, 404
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusNotFound)
	if err := json.NewEncoder(w).Encode(jsonErr{Code: http.StatusNotFound, Text: "Not Found"}); err != nil {
		panic(err)
	}
}

//handlers for court
func CourtIndex(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusOK)
	if err := json.NewEncoder(w).Encode(courts); err != nil {
		panic(err)
	}
}

func CourtCreate(w http.ResponseWriter, r *http.Request){

  var court Court
	var err error
  //Check if malicious user is trying to overload the server
  body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1048576))
  if err != nil{
    panic(err)
  }
  if err := r.Body.Close(); err != nil{
    panic(err)
  }
  if err := json.Unmarshal(body, &court); err != nil{
    w.Header().Set("Content-Type", "application/json; charset=UTF-8")

		w.WriteHeader(422) // unprocessable entity
		if err := json.NewEncoder(w).Encode(err); err != nil {
			panic(err)
		}

  }
  if court, err = RepoCreateCourt(court); err != nil {
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		w.WriteHeader(422) // unprocessable entity
		if err := json.NewEncoder(w).Encode(err); err != nil {
			panic(err)
		}
	}
  w.Header().Set("Content-Type", "application/json; charset=UTF-8")
  w.WriteHeader(http.StatusCreated)
  if err := json.NewEncoder(w).Encode(court); err != nil {
    panic(err)
  }
}

func CourtUpdate(w http.ResponseWriter, r *http.Request) {

	vars := mux.Vars(r)
	var courtId int
	var err error

	if courtId, err = strconv.Atoi(vars["courtId"]); err != nil {
		panic(err)
	}

	var court Court
	//Check if malicious user is trying to overload the server
	body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1048576))
	if err != nil {
		panic(err)
	}
	if err := r.Body.Close(); err != nil {
		panic(err)
	}
	if err := json.Unmarshal(body, &court); err != nil {
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		w.WriteHeader(422) // unprocessable entity
		if err := json.NewEncoder(w).Encode(err); err != nil {
			panic(err)
		}
	}

  if err := RepoUpdateCourt(&court, courtId); err != nil{
    w.Header().Set("Content-Type", "application/json; charset=UTF-8")
    w.WriteHeader(http.StatusNotFound) //TODO: Use right status code
    if err := json.NewEncoder(w).Encode(jsonErr{Code: http.StatusNotFound, Text: "Not Found"}); err != nil {
      panic(err)
    }
  }
  w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusOK) // TODO: Use right status code

	if err := json.NewEncoder(w).Encode(court); err != nil {
		panic(err)
	}
}

func CourtDelete(w http.ResponseWriter, r *http.Request){
	vars := mux.Vars(r)
  var courtId int
  var err error

  if courtId, err = strconv.Atoi(vars["courtId"]); err != nil{
    panic(err)
  }

	if err := RepoDeleteCourt(courtId); err!= nil {
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
    w.WriteHeader(http.StatusNotFound) //TODO: Use right status code
    if err := json.NewEncoder(w).Encode(jsonErr{Code: http.StatusNotFound, Text: "Not Found"}); err != nil {
      panic(err)
    }
	} else {
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
    w.WriteHeader(http.StatusOK)
		if err := json.NewEncoder(w).Encode(jsonErr{Code: http.StatusOK, Text: "Item Deleted"}); err != nil {
      panic(err)
    }
	}
}

func CourtShow(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	var courtId int
	var err error

	if courtId, err = strconv.Atoi(vars["courtId"]); err != nil {
		panic(err)
	}

	court := RepoFindCourt(courtId)
	if court.Id > 0 {
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		w.WriteHeader(http.StatusOK)
		if err := json.NewEncoder(w).Encode(court); err != nil {
			panic(err)
		}
		return
	}

	// If we didn't find it, 404
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusNotFound)
	if err := json.NewEncoder(w).Encode(jsonErr{Code: http.StatusNotFound, Text: "Not Found"}); err != nil {
		panic(err)
	}
}

//handlers for Ticket
func TicketIndex(w http.ResponseWriter, r *http.Request) {
	params := r.URL.Query()
	driver_licenses, ok := params["driver_license"]
	if ok {
		driver_license := string(driver_licenses[0])
		tic := RepoFindTicketByDriverLicenseNumber(driver_license)
		if tic.Id <=0 {
			w.Header().Set("Content-Type", "application/json; charset=UTF-8")
			w.WriteHeader(http.StatusOK)
			if err := json.NewEncoder(w).Encode(tic); err != nil {
				panic(err)
			}
		}else {
			w.Header().Set("Content-Type", "application/json; charset=UTF-8")
			w.WriteHeader(http.StatusNotFound)
			if err := json.NewEncoder(w).Encode(jsonErr{Code: http.StatusNotFound, Text: "Not Found"}); err != nil {
				panic(err)
			}
		}
	} else {
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		w.WriteHeader(http.StatusOK)
		if err := json.NewEncoder(w).Encode(gTickets); err != nil {
			panic(err)
		}
	}
}

func TicketCreate(w http.ResponseWriter, r *http.Request){

  var ticket Ticket
	var err error
  //Check if malicious user is trying to overload the server
  body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1048576))
  if err != nil{
    panic(err)
  }
  if err := r.Body.Close(); err != nil{
    panic(err)
  }
  if err := json.Unmarshal(body, &ticket); err != nil{
    w.Header().Set("Content-Type", "application/json; charset=UTF-8")

		w.WriteHeader(422) // unprocessable entity
		if err := json.NewEncoder(w).Encode(err); err != nil {
			panic(err)
		}

  }
  if ticket, err = RepoCreateTicket(ticket); err != nil {
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		w.WriteHeader(422) // unprocessable entity
		if err := json.NewEncoder(w).Encode(err); err != nil {
			panic(err)
		}
	}
  w.Header().Set("Content-Type", "application/json; charset=UTF-8")
  w.WriteHeader(http.StatusCreated)
  if err := json.NewEncoder(w).Encode(ticket); err != nil {
    panic(err)
  }
}

func TicketUpdate(w http.ResponseWriter, r *http.Request) {

	vars := mux.Vars(r)
	var ticketId int
	var err error

	if ticketId, err = strconv.Atoi(vars["ticketId"]); err != nil {
		panic(err)
	}

	var ticket Ticket
	//Check if malicious user is trying to overload the server
	body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1048576))
	if err != nil {
		panic(err)
	}
	if err := r.Body.Close(); err != nil {
		panic(err)
	}
	if err := json.Unmarshal(body, &ticket); err != nil {
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		w.WriteHeader(422) // unprocessable entity
		if err := json.NewEncoder(w).Encode(err); err != nil {
			panic(err)
		}
	}

  if err := RepoUpdateTicket(&ticket, ticketId); err != nil{
    w.Header().Set("Content-Type", "application/json; charset=UTF-8")
    w.WriteHeader(http.StatusNotFound) //TODO: Use right status code
    if err := json.NewEncoder(w).Encode(jsonErr{Code: http.StatusNotFound, Text: "Not Found"}); err != nil {
      panic(err)
    }
  }
  w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusOK) // TODO: Use right status code

	if err := json.NewEncoder(w).Encode(ticket); err != nil {
		panic(err)
	}
}

func TicketDelete(w http.ResponseWriter, r *http.Request){
	vars := mux.Vars(r)
  var ticketId int
  var err error

  if ticketId, err = strconv.Atoi(vars["ticketId"]); err != nil{
    panic(err)
  }

	if err := RepoDeleteTicket(ticketId); err!= nil {
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
    w.WriteHeader(http.StatusNotFound) //TODO: Use right status code
    if err := json.NewEncoder(w).Encode(jsonErr{Code: http.StatusNotFound, Text: "Not Found"}); err != nil {
      panic(err)
    }
	} else {
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
    w.WriteHeader(http.StatusOK)
		if err := json.NewEncoder(w).Encode(jsonErr{Code: http.StatusOK, Text: "Item Deleted"}); err != nil {
      panic(err)
    }
	}
}

func TicketShow(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	var ticketId int
	var err error

	if ticketId, err = strconv.Atoi(vars["ticketId"]); err != nil {
		panic(err)
	}

	ticket := RepoFindTicket(ticketId)
	if ticket.Id > 0 {
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		w.WriteHeader(http.StatusOK)
		if err := json.NewEncoder(w).Encode(ticket); err != nil {
			panic(err)
		}
		return
	}

	// If we didn't find it, 404
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusNotFound)
	if err := json.NewEncoder(w).Encode(jsonErr{Code: http.StatusNotFound, Text: "Not Found"}); err != nil {
		panic(err)
	}
}

/*
Example of JSON data structure
{
  "id":"1",
  "key":"value",
  "key2":["value1","value2"]
}
*/

/*
Test with this curl command:
curl -H "Content-Type: application/json" -d '{"name":"New Todo"}' http://localhost:8080/todos
*/
<|endoftext|>


<commit_before>// Package main ...
package main

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

	"github.com/microplatform-io/platform"
)

// ServerDiscoveryHandler - Will return (based on content type) service discovery details
func ServerDiscoveryHandler(server *Server) func(w http.ResponseWriter, req *http.Request) {
	return func(w http.ResponseWriter, req *http.Request) {
		cb := req.FormValue("callback")

		jsonBytes, _ := json.Marshal(map[string]string{
			"protocol": serverProtocol,
			"host":     server.GetFormattedHostAddr(),
			"port":     server.Options.Port,
		})

		if cb == "" {
			w.Header().Set("Content-Type", "application/json")
			w.Write(jsonBytes)
			return
		}

		w.Header().Set("Content-Type", "application/javascript")
		fmt.Fprintf(w, fmt.Sprintf("%s(%s)", cb, jsonBytes))
	}
}

// MicroplatformEndpointHandler -
func MicroplatformEndpointHandler(server *Server) func(w http.ResponseWriter, req *http.Request) {
	return func(w http.ResponseWriter, req *http.Request) {
		w.Header().Set("Content-Type", "application/json")

		contents, err := ioutil.ReadAll(req.Body)

		if err != nil {
			w.Write(ErrorResponse(fmt.Sprintf("Failed to read body: %s", err)))
			return
		}

		platformRequestBytes, err := hex.DecodeString(fmt.Sprintf("%s", contents))

		if err != nil {
			w.Write(ErrorResponse(fmt.Sprintf("Failed to decode body: %s", err)))
			return
		}

		platformRequest := &platform.Request{}

		if err := platform.Unmarshal(platformRequestBytes, platformRequest); err != nil {
			w.Write(ErrorResponse(fmt.Sprintf("Failed to unmarshal platform request: %s", err)))
			return
		}

		if platformRequest.Routing == nil {
			platformRequest.Routing = &platform.Routing{}
		}

		if !platform.RouteToSchemeMatches(platformRequest, "microservice") {
			w.Write(ErrorResponse(fmt.Sprintf("Unsupported scheme provided: %s", platformRequest.Routing.RouteTo)))
			return
		}

		responses, timeout := server.Router.Route(platformRequest)

		for {
			select {
			case response := <-responses:
				logger.Printf("Got a response for request:", platformRequest.GetUuid())

				responseBytes, err := platform.Marshal(response)

				if err != nil {
					w.Write(ErrorResponse(fmt.Sprintf(
						"failed to marshal platform request: %s - err: %s", platformRequest.GetUuid(), err,
					)))
					return
				}

				w.Write(responseBytes)

			case <-timeout:
				w.Write(ErrorResponse(fmt.Sprintf("Got a timeout for request: %s", platformRequest.GetUuid())))
				return
			}
		}

		return
	}
}
<commit_msg>Making sure that we do not return heartbeat response<commit_after>// Package main ...
package main

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

	"github.com/microplatform-io/platform"
)

// ServerDiscoveryHandler - Will return (based on content type) service discovery details
func ServerDiscoveryHandler(server *Server) func(w http.ResponseWriter, req *http.Request) {
	return func(w http.ResponseWriter, req *http.Request) {
		cb := req.FormValue("callback")

		jsonBytes, _ := json.Marshal(map[string]string{
			"protocol": serverProtocol,
			"host":     server.GetFormattedHostAddr(),
			"port":     server.Options.Port,
		})

		if cb == "" {
			w.Header().Set("Content-Type", "application/json")
			w.Write(jsonBytes)
			return
		}

		w.Header().Set("Content-Type", "application/javascript")
		fmt.Fprintf(w, fmt.Sprintf("%s(%s)", cb, jsonBytes))
	}
}

// MicroplatformEndpointHandler -
func MicroplatformEndpointHandler(server *Server) func(w http.ResponseWriter, req *http.Request) {
	return func(w http.ResponseWriter, req *http.Request) {
		w.Header().Set("Content-Type", "application/json")

		contents, err := ioutil.ReadAll(req.Body)

		if err != nil {
			w.Write(ErrorResponse(fmt.Sprintf("Failed to read body: %s", err)))
			return
		}

		platformRequestBytes, err := hex.DecodeString(fmt.Sprintf("%s", contents))

		if err != nil {
			w.Write(ErrorResponse(fmt.Sprintf("Failed to decode body: %s", err)))
			return
		}

		platformRequest := &platform.Request{}

		if err := platform.Unmarshal(platformRequestBytes, platformRequest); err != nil {
			w.Write(ErrorResponse(fmt.Sprintf("Failed to unmarshal platform request: %s", err)))
			return
		}

		if platformRequest.Routing == nil {
			platformRequest.Routing = &platform.Routing{}
		}

		if platformRequest.Routing.RouteFrom != nil {
			platformRequest.Routing.RouteFrom = []*platform.Route{}
		}

		if !platform.RouteToSchemeMatches(platformRequest, "microservice") {
			w.Write(ErrorResponse(fmt.Sprintf("Unsupported scheme provided: %s", platformRequest.Routing.RouteTo)))
			return
		}

		responses, timeout := server.Router.Route(platformRequest)

		for {
			select {
			case response := <-responses:
				logger.Printf("Got a response for request:", platformRequest.GetUuid())

				if response.GetRouting().GetRouteTo()[0].GetUri() != "resource:///heartbeat" {

					responseBytes, err := platform.Marshal(response)

					if err != nil {
						w.Write(ErrorResponse(fmt.Sprintf(
							"failed to marshal platform request: %s - err: %s", platformRequest.GetUuid(), err,
						)))
						return
					}

					w.Write([]byte(hex.EncodeToString(responseBytes)))
					return

				}

			case <-timeout:
				w.Write(ErrorResponse(fmt.Sprintf("Got a timeout for request: %s", platformRequest.GetUuid())))
				return
			}
		}

		return
	}
}
<|endoftext|>


<commit_before>// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package atomic

import (
	"unsafe"
)

// A Value provides an atomic load and store of a consistently typed value.
// The zero value for a Value returns nil from Load.
// Once Store has been called, a Value must not be copied.
//
// A Value must not be copied after first use.
type Value struct {
	v interface{}
}

// ifaceWords is interface{} internal representation.
type ifaceWords struct {
	typ  unsafe.Pointer
	data unsafe.Pointer
}

// Load returns the value set by the most recent Store.
// It returns nil if there has been no call to Store for this Value.
func (v *Value) Load() (val interface{}) {
	vp := (*ifaceWords)(unsafe.Pointer(v))
	typ := LoadPointer(&vp.typ)
	if typ == nil || uintptr(typ) == ^uintptr(0) {
		// First store not yet completed.
		return nil
	}
	data := LoadPointer(&vp.data)
	vlp := (*ifaceWords)(unsafe.Pointer(&val))
	vlp.typ = typ
	vlp.data = data
	return
}

// Store sets the value of the Value to x.
// All calls to Store for a given Value must use values of the same concrete type.
// Store of an inconsistent type panics, as does Store(nil).
func (v *Value) Store(val interface{}) {
	if val == nil {
		panic("sync/atomic: store of nil value into Value")
	}
	vp := (*ifaceWords)(unsafe.Pointer(v))
	vlp := (*ifaceWords)(unsafe.Pointer(&val))
	for {
		typ := LoadPointer(&vp.typ)
		if typ == nil {
			// Attempt to start first store.
			// Disable preemption so that other goroutines can use
			// active spin wait to wait for completion; and so that
			// GC does not see the fake type accidentally.
			runtime_procPin()
			if !CompareAndSwapPointer(&vp.typ, nil, unsafe.Pointer(^uintptr(0))) {
				runtime_procUnpin()
				continue
			}
			// Complete first store.
			StorePointer(&vp.data, vlp.data)
			StorePointer(&vp.typ, vlp.typ)
			runtime_procUnpin()
			return
		}
		if uintptr(typ) == ^uintptr(0) {
			// First store in progress. Wait.
			// Since we disable preemption around the first store,
			// we can wait with active spinning.
			continue
		}
		// First store completed. Check type and overwrite data.
		if typ != vlp.typ {
			panic("sync/atomic: store of inconsistently typed value into Value")
		}
		StorePointer(&vp.data, vlp.data)
		return
	}
}

// Swap stores new into Value and returns the previous value. It returns nil if
// the Value is empty.
//
// All calls to Swap for a given Value must use values of the same concrete
// type. Swap of an inconsistent type panics, as does Swap(nil).
func (v *Value) Swap(new interface{}) (old interface{}) {
	if new == nil {
		panic("sync/atomic: swap of nil value into Value")
	}
	vp := (*ifaceWords)(unsafe.Pointer(v))
	np := (*ifaceWords)(unsafe.Pointer(&new))
	for {
		typ := LoadPointer(&vp.typ)
		if typ == nil {
			// Attempt to start first store.
			// Disable preemption so that other goroutines can use
			// active spin wait to wait for completion; and so that
			// GC does not see the fake type accidentally.
			runtime_procPin()
			if !CompareAndSwapPointer(&vp.typ, nil, unsafe.Pointer(^uintptr(0))) {
				runtime_procUnpin()
				continue
			}
			// Complete first store.
			StorePointer(&vp.data, np.data)
			StorePointer(&vp.typ, np.typ)
			runtime_procUnpin()
			return nil
		}
		if uintptr(typ) == ^uintptr(0) {
			// First store in progress. Wait.
			// Since we disable preemption around the first store,
			// we can wait with active spinning.
			continue
		}
		// First store completed. Check type and overwrite data.
		if typ != np.typ {
			panic("sync/atomic: swap of inconsistently typed value into Value")
		}
		op := (*ifaceWords)(unsafe.Pointer(&old))
		op.typ, op.data = np.typ, SwapPointer(&vp.data, np.data)
		return old
	}
}

// CompareAndSwapPointer executes the compare-and-swap operation for the Value.
//
// All calls to CompareAndSwap for a given Value must use values of the same
// concrete type. CompareAndSwap of an inconsistent type panics, as does
// CompareAndSwap(old, nil).
func (v *Value) CompareAndSwap(old, new interface{}) (swapped bool) {
	if new == nil {
		panic("sync/atomic: compare and swap of nil value into Value")
	}
	vp := (*ifaceWords)(unsafe.Pointer(v))
	np := (*ifaceWords)(unsafe.Pointer(&new))
	op := (*ifaceWords)(unsafe.Pointer(&old))
	if op.typ != nil && np.typ != op.typ {
		panic("sync/atomic: compare and swap of inconsistently typed values")
	}
	for {
		typ := LoadPointer(&vp.typ)
		if typ == nil {
			if old != nil {
				return false
			}
			// Attempt to start first store.
			// Disable preemption so that other goroutines can use
			// active spin wait to wait for completion; and so that
			// GC does not see the fake type accidentally.
			runtime_procPin()
			if !CompareAndSwapPointer(&vp.typ, nil, unsafe.Pointer(^uintptr(0))) {
				runtime_procUnpin()
				continue
			}
			// Complete first store.
			StorePointer(&vp.data, np.data)
			StorePointer(&vp.typ, np.typ)
			runtime_procUnpin()
			return true
		}
		if uintptr(typ) == ^uintptr(0) {
			// First store in progress. Wait.
			// Since we disable preemption around the first store,
			// we can wait with active spinning.
			continue
		}
		// First store completed. Check type and overwrite data.
		if typ != np.typ {
			panic("sync/atomic: compare and swap of inconsistently typed value into Value")
		}
		// Compare old and current via runtime equality check.
		// This allows value types to be compared, something
		// not offered by the package functions.
		// CompareAndSwapPointer below only ensures vp.data
		// has not changed since LoadPointer.
		data := LoadPointer(&vp.data)
		var i interface{}
		(*ifaceWords)(unsafe.Pointer(&i)).typ = typ
		(*ifaceWords)(unsafe.Pointer(&i)).data = data
		if i != old {
			return false
		}
		return CompareAndSwapPointer(&vp.data, data, np.data)
	}
}

// Disable/enable preemption, implemented in runtime.
func runtime_procPin()
func runtime_procUnpin()
<commit_msg>sync/atomic: fix documentation for CompareAndSwap<commit_after>// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package atomic

import (
	"unsafe"
)

// A Value provides an atomic load and store of a consistently typed value.
// The zero value for a Value returns nil from Load.
// Once Store has been called, a Value must not be copied.
//
// A Value must not be copied after first use.
type Value struct {
	v interface{}
}

// ifaceWords is interface{} internal representation.
type ifaceWords struct {
	typ  unsafe.Pointer
	data unsafe.Pointer
}

// Load returns the value set by the most recent Store.
// It returns nil if there has been no call to Store for this Value.
func (v *Value) Load() (val interface{}) {
	vp := (*ifaceWords)(unsafe.Pointer(v))
	typ := LoadPointer(&vp.typ)
	if typ == nil || uintptr(typ) == ^uintptr(0) {
		// First store not yet completed.
		return nil
	}
	data := LoadPointer(&vp.data)
	vlp := (*ifaceWords)(unsafe.Pointer(&val))
	vlp.typ = typ
	vlp.data = data
	return
}

// Store sets the value of the Value to x.
// All calls to Store for a given Value must use values of the same concrete type.
// Store of an inconsistent type panics, as does Store(nil).
func (v *Value) Store(val interface{}) {
	if val == nil {
		panic("sync/atomic: store of nil value into Value")
	}
	vp := (*ifaceWords)(unsafe.Pointer(v))
	vlp := (*ifaceWords)(unsafe.Pointer(&val))
	for {
		typ := LoadPointer(&vp.typ)
		if typ == nil {
			// Attempt to start first store.
			// Disable preemption so that other goroutines can use
			// active spin wait to wait for completion; and so that
			// GC does not see the fake type accidentally.
			runtime_procPin()
			if !CompareAndSwapPointer(&vp.typ, nil, unsafe.Pointer(^uintptr(0))) {
				runtime_procUnpin()
				continue
			}
			// Complete first store.
			StorePointer(&vp.data, vlp.data)
			StorePointer(&vp.typ, vlp.typ)
			runtime_procUnpin()
			return
		}
		if uintptr(typ) == ^uintptr(0) {
			// First store in progress. Wait.
			// Since we disable preemption around the first store,
			// we can wait with active spinning.
			continue
		}
		// First store completed. Check type and overwrite data.
		if typ != vlp.typ {
			panic("sync/atomic: store of inconsistently typed value into Value")
		}
		StorePointer(&vp.data, vlp.data)
		return
	}
}

// Swap stores new into Value and returns the previous value. It returns nil if
// the Value is empty.
//
// All calls to Swap for a given Value must use values of the same concrete
// type. Swap of an inconsistent type panics, as does Swap(nil).
func (v *Value) Swap(new interface{}) (old interface{}) {
	if new == nil {
		panic("sync/atomic: swap of nil value into Value")
	}
	vp := (*ifaceWords)(unsafe.Pointer(v))
	np := (*ifaceWords)(unsafe.Pointer(&new))
	for {
		typ := LoadPointer(&vp.typ)
		if typ == nil {
			// Attempt to start first store.
			// Disable preemption so that other goroutines can use
			// active spin wait to wait for completion; and so that
			// GC does not see the fake type accidentally.
			runtime_procPin()
			if !CompareAndSwapPointer(&vp.typ, nil, unsafe.Pointer(^uintptr(0))) {
				runtime_procUnpin()
				continue
			}
			// Complete first store.
			StorePointer(&vp.data, np.data)
			StorePointer(&vp.typ, np.typ)
			runtime_procUnpin()
			return nil
		}
		if uintptr(typ) == ^uintptr(0) {
			// First store in progress. Wait.
			// Since we disable preemption around the first store,
			// we can wait with active spinning.
			continue
		}
		// First store completed. Check type and overwrite data.
		if typ != np.typ {
			panic("sync/atomic: swap of inconsistently typed value into Value")
		}
		op := (*ifaceWords)(unsafe.Pointer(&old))
		op.typ, op.data = np.typ, SwapPointer(&vp.data, np.data)
		return old
	}
}

// CompareAndSwap executes the compare-and-swap operation for the Value.
//
// All calls to CompareAndSwap for a given Value must use values of the same
// concrete type. CompareAndSwap of an inconsistent type panics, as does
// CompareAndSwap(old, nil).
func (v *Value) CompareAndSwap(old, new interface{}) (swapped bool) {
	if new == nil {
		panic("sync/atomic: compare and swap of nil value into Value")
	}
	vp := (*ifaceWords)(unsafe.Pointer(v))
	np := (*ifaceWords)(unsafe.Pointer(&new))
	op := (*ifaceWords)(unsafe.Pointer(&old))
	if op.typ != nil && np.typ != op.typ {
		panic("sync/atomic: compare and swap of inconsistently typed values")
	}
	for {
		typ := LoadPointer(&vp.typ)
		if typ == nil {
			if old != nil {
				return false
			}
			// Attempt to start first store.
			// Disable preemption so that other goroutines can use
			// active spin wait to wait for completion; and so that
			// GC does not see the fake type accidentally.
			runtime_procPin()
			if !CompareAndSwapPointer(&vp.typ, nil, unsafe.Pointer(^uintptr(0))) {
				runtime_procUnpin()
				continue
			}
			// Complete first store.
			StorePointer(&vp.data, np.data)
			StorePointer(&vp.typ, np.typ)
			runtime_procUnpin()
			return true
		}
		if uintptr(typ) == ^uintptr(0) {
			// First store in progress. Wait.
			// Since we disable preemption around the first store,
			// we can wait with active spinning.
			continue
		}
		// First store completed. Check type and overwrite data.
		if typ != np.typ {
			panic("sync/atomic: compare and swap of inconsistently typed value into Value")
		}
		// Compare old and current via runtime equality check.
		// This allows value types to be compared, something
		// not offered by the package functions.
		// CompareAndSwapPointer below only ensures vp.data
		// has not changed since LoadPointer.
		data := LoadPointer(&vp.data)
		var i interface{}
		(*ifaceWords)(unsafe.Pointer(&i)).typ = typ
		(*ifaceWords)(unsafe.Pointer(&i)).data = data
		if i != old {
			return false
		}
		return CompareAndSwapPointer(&vp.data, data, np.data)
	}
}

// Disable/enable preemption, implemented in runtime.
func runtime_procPin()
func runtime_procUnpin()
<|endoftext|>


<commit_before>// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build cgo,!netgo
// +build darwin dragonfly freebsd linux netbsd openbsd

package net

import "testing"

func TestCgoLookupIP(t *testing.T) {
	host := "localhost"
	_, err, ok := cgoLookupIP(host)
	if !ok {
		t.Errorf("cgoLookupIP must not be a placeholder")
	}
	if err != nil {
		t.Error(err)
	}
	if _, err := goLookupIP(host); err != nil {
		t.Error(err)
	}
}
<commit_msg>net: enable cgo test on solaris<commit_after>// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build cgo,!netgo
// +build darwin dragonfly freebsd linux netbsd openbsd solaris

package net

import "testing"

func TestCgoLookupIP(t *testing.T) {
	host := "localhost"
	_, err, ok := cgoLookupIP(host)
	if !ok {
		t.Errorf("cgoLookupIP must not be a placeholder")
	}
	if err != nil {
		t.Error(err)
	}
	if _, err := goLookupIP(host); err != nil {
		t.Error(err)
	}
}
<|endoftext|>