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

package main

import (
	"flag"
	"log"
	"net/http"
	"os"
	"path/filepath"

	"github.com/mb0/lab/golab/gosrc"
	"github.com/mb0/lab/golab/hub"
	"github.com/mb0/lab/ws"
)

var (
	httpstart = flag.Bool("http", false, "start http server")
	httpaddr  = flag.String("addr", "localhost:8910", "http server addr")
)

func init() {
	flag.Parse()
	if !*httpstart {
		return
	}
	log.Printf("starting http://%s/\n", *httpaddr)
	serveclient()
	lab.mods = append(lab.mods, &httpmod{})
}

type httpmod struct {
	*hub.Hub
}

func (mod *httpmod) Start() {
	mod.Hub = hub.New(func(h *hub.Hub, m hub.Msg, id hub.Id) {
		switch m.Head {
		case hub.Signon.Head:
			// send reports for all working packages
			msg, err := hub.Marshal("reports", lab.src.AllReports())
			if err != nil {
				log.Println(err)
				return
			}
			h.SendMsg(msg, id)
		case "stat":
			var path string
			err := m.Unmarshal(&path)
			if err != nil {
				log.Println(err)
				return
			}
			msg, err := apistat(path)
			if err != nil {
				log.Println(err)
				return
			}
			h.SendMsg(msg, id)
		default:
			// echo messages
			h.SendMsg(m, id)
		}
	})
	lab.src.SignalReports(func(r *gosrc.Report) {
		m, err := hub.Marshal("report", r)
		if err != nil {
			log.Println(err)
			return
		}
		mod.SendMsg(m, hub.Group)
	})
	http.Handle("/ws", mod.Hub)
	err := http.ListenAndServe(*httpaddr, nil)
	if err != nil {
		log.Fatalf("http %s\n", err)
	}
}

func (mod *httpmod) Filter(r *ws.Res) bool {
	return false
}

func (mod *httpmod) Handle(op ws.Op, r *ws.Res) {
}

func apistat(path string) (hub.Msg, error) {
	res := apires{ws.NewId(path), path}
	if r := lab.ws.Res(res.Id); r != nil {
		res.Name = r.Name
		if r.Dir != nil {
			cs := make([]apires, 0, len(r.Children))
			for _, c := range r.Children {
				cs = append(cs, apires{c.Id, c.Name})
			}
			return hub.Marshal("stat", struct {
				apires
				Path     string
				Children []apires
			}{res, path, cs})
		}
		return hub.Marshal("stat", struct {
			apires
			Path string
		}{res, path})
	}
	return hub.Marshal("stat.err", struct {
		apires
		Path  string
		Error string
	}{res, path, "not found"})
}

type apires struct {
	Id   ws.Id `json:",string"`
	Name string
}

func serveclient() {
	http.HandleFunc("/", index)
	if static := findstatic(); static == "" {
		indexbytes = []byte("cannot find client files.")
	} else {
		http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir(static))))
	}
}

func index(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path != "/" {
		http.NotFound(w, r)
		return
	}
	if r.Method != "GET" {
		http.Error(w, "Method nod allowed", 405)
		return
	}
	w.Header().Set("Content-Type", "text/html; charset=utf-8")
	w.Write(indexbytes)
}

var indexbytes = []byte(`<!DOCTYPE html>
<html lang="en"><head>
	<title>golab</title>
	<meta charset="utf-8">
	<link href="/static/main.css" rel="stylesheet">
</head><body>
	<div id="app"></div>
	<script data-main="/static/main" src="/static/require.js"></script>
</body></html>
`)

func findstatic() string {
	for _, dir := range lab.dirs {
		path := filepath.Join(dir, "github.com/mb0/lab/golab/static")
		_, err := os.Stat(path)
		if err == nil {
			return path
		}
	}
	return ""
}<commit_msg>http server serves raw file contents of workspace resources.<commit_after>// Copyright 2013 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"flag"
	"io"
	"log"
	"net/http"
	"os"
	"path/filepath"

	"github.com/mb0/lab/golab/gosrc"
	"github.com/mb0/lab/golab/hub"
	"github.com/mb0/lab/ws"
)

var (
	httpstart = flag.Bool("http", false, "start http server")
	httpaddr  = flag.String("addr", "localhost:8910", "http server addr")
)

func init() {
	flag.Parse()
	if !*httpstart {
		return
	}
	log.Printf("starting http://%s/\n", *httpaddr)
	serveclient()
	lab.mods = append(lab.mods, &httpmod{})
}

type httpmod struct {
	*hub.Hub
}

func (mod *httpmod) Start() {
	mod.Hub = hub.New(func(h *hub.Hub, m hub.Msg, id hub.Id) {
		switch m.Head {
		case hub.Signon.Head:
			// send reports for all working packages
			msg, err := hub.Marshal("reports", lab.src.AllReports())
			if err != nil {
				log.Println(err)
				return
			}
			h.SendMsg(msg, id)
		case "stat":
			var path string
			err := m.Unmarshal(&path)
			if err != nil {
				log.Println(err)
				return
			}
			msg, err := apistat(path)
			if err != nil {
				log.Println(err)
				return
			}
			h.SendMsg(msg, id)
		default:
			// echo messages
			h.SendMsg(m, id)
		}
	})
	lab.src.SignalReports(func(r *gosrc.Report) {
		m, err := hub.Marshal("report", r)
		if err != nil {
			log.Println(err)
			return
		}
		mod.SendMsg(m, hub.Group)
	})
	http.Handle("/ws", mod.Hub)
	err := http.ListenAndServe(*httpaddr, nil)
	if err != nil {
		log.Fatalf("http %s\n", err)
	}
}

func (mod *httpmod) Filter(r *ws.Res) bool {
	return false
}

func (mod *httpmod) Handle(op ws.Op, r *ws.Res) {
}

func apistat(path string) (hub.Msg, error) {
	res := apires{ws.NewId(path), path, false}
	if r := lab.ws.Res(res.Id); r != nil {
		r.Lock()
		defer r.Unlock()
		res.Name, res.IsDir = r.Name, r.Flag&ws.FlagDir != 0
		if r.Dir != nil {
			cs := make([]apires, 0, len(r.Children))
			for _, c := range r.Children {
				if c.Flag&ws.FlagIgnore == 0 {
					cs = append(cs, apires{c.Id, c.Name, c.Flag&ws.FlagDir != 0})
				}
			}
			return hub.Marshal("stat", struct {
				apires
				Path     string
				Children []apires
			}{res, path, cs})
		}
		return hub.Marshal("stat", struct {
			apires
			Path string
		}{res, path})
	}
	return hub.Marshal("stat.err", struct {
		apires
		Path  string
		Error string
	}{res, path, "not found"})
}

type apires struct {
	Id    ws.Id `json:",string"`
	Name  string
	IsDir bool
}

func serveclient() {
	http.HandleFunc("/", index)
	if static := findstatic(); static == "" {
		indexbytes = []byte("cannot find client files.")
	} else {
		http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir(static))))
	}
	http.HandleFunc("/raw/", raw)
}

func index(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path != "/" {
		http.NotFound(w, r)
		return
	}
	if r.Method != "GET" {
		http.Error(w, "Method nod allowed", 405)
		return
	}
	w.Header().Set("Content-Type", "text/html; charset=utf-8")
	w.Write(indexbytes)
}

var indexbytes = []byte(`<!DOCTYPE html>
<html lang="en"><head>
	<title>golab</title>
	<meta charset="utf-8">
	<link href="/static/main.css" rel="stylesheet">
</head><body>
	<div id="app"></div>
	<script data-main="/static/main" src="/static/require.js"></script>
</body></html>
`)

func findstatic() string {
	for _, dir := range lab.dirs {
		path := filepath.Join(dir, "github.com/mb0/lab/golab/static")
		_, err := os.Stat(path)
		if err == nil {
			return path
		}
	}
	return ""
}

func raw(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path[:5] != "/raw/" {
		http.NotFound(w, r)
		return
	}
	if r.Method != "GET" {
		http.Error(w, "Method nod allowed", 405)
		return
	}
	path := r.URL.Path[4:]
	if res := lab.ws.Res(ws.NewId(path)); res == nil || res.Flag&(ws.FlagDir|ws.FlagIgnore) != 0 {
		http.NotFound(w, r)
		return
	}
	f, err := os.Open(path)
	if err != nil {
		http.NotFound(w, r)
		return
	}
	defer f.Close()
	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
	_, err = io.Copy(w, f)
	if err != nil {
		log.Println(err)
	}
}
{'fraction_non_alphanumeric': 0.18381962864721485, 'fraction_numerical': 0.00610079575596817, 'mean_word_length': 3.1686014372581535, 'pattern_counts': {'":': 2, '<': 35, '<?xml version=': 0, '>': 35, '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': '1621403', 'n_tokens_mistral': 3243, 'n_tokens_neox': 2948, 'n_words': 700}