Ejemplo n.º 1
0
func UseTicket(tickets util.Ticket_struct) (string, error) {
	fmt.Printf("Accessing NEO4J Server Cyphering UseTicket\n")
	database, err := neoism.Connect("http://*****:*****@localhost:7474/db/data")

	if err != nil {
		fmt.Printf("NEO4J Connection FAILED\n")
		return "Internal Service Error", err
	}

	cq := neoism.CypherQuery{
		Statement: `
		MATCH (t:Ticket)
		WHERE t.ID = {user_id} AND t.COUPON_ID = {id}
		SET t.VALID = "FALSE"
	`,
		Parameters: neoism.Props{"user_id": tickets.ID, "id": tickets.COUPON_ID},
	}
	err = database.Cypher(&cq)
	if err != nil {
		fmt.Printf("Error Cyphering To Database\n")
		return "Internal Service Error", err
	}

	return "Success", nil
}
func runServer(neoURL string, port int) {
	var err error
	db, err = neoism.Connect(neoURL)
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("connected to %s\n", neoURL)
	neoutils.EnsureIndexes(db, map[string]string{
		"Thing": "uuid",
	})

	m := mux.NewRouter()
	http.Handle("/", m)

	m.HandleFunc("/content/{content_uuid}/annotations/annotated_by/{concept_uuid}", writeHandler).Methods("PUT")
	m.HandleFunc("/annotations/", allWriteHandler).Methods("PUT")
	cw = neocypherrunner.NewBatchCypherRunner(neoutils.StringerDb{db}, 1024)

	log.Printf("listening on %d", port)
	if err := http.ListenAndServe(fmt.Sprintf(":%d", port), nil); err != nil {
		log.Printf("web stuff failed: %v\n", err)
	}

}
Ejemplo n.º 3
0
func connect() *neoism.Database {
	db, err := neoism.Connect("http://localhost:7474/db/data")
	if err != nil {
		log.Fatal(err)
	}
	return db
}
Ejemplo n.º 4
0
func connectDefault(neoURL string, conf *ConnectionConfig) (NeoConnection, error) {

	db, err := neoism.Connect(neoURL)
	if err != nil {
		return nil, err
	}

	if conf.HTTPClient != nil {
		db.Session.Client = conf.HTTPClient
	}

	exeName, err := osutil.Executable()
	if err == nil {
		_, exeFile := filepath.Split(exeName)
		db.Session.Header.Set("User-Agent", exeFile+" (using neoutils)")
	}

	var cr CypherRunner = db
	if conf.Transactional {
		cr = TransactionalCypherRunner{db}
	} else {
		cr = db
	}

	if conf.BatchSize > 0 {
		cr = NewBatchCypherRunner(cr, conf.BatchSize)
	}

	ie := &defaultIndexEnsurer{db}

	return &DefaultNeoConnection{neoURL, cr, ie, db}, nil
}
Ejemplo n.º 5
0
func UrlsIndexHandler(w http.ResponseWriter, req *http.Request) {
	neo, err := neoism.Connect(os.Getenv("GRAPHENEDB_URL"))

	if err != nil {
		printer.JSON(w, http.StatusServiceUnavailable, map[string]interface{}{
			"code":    http.StatusServiceUnavailable,
			"error":   http.StatusText(http.StatusServiceUnavailable),
			"message": err,
		})
	} else {
		urls := []Url{}
		cq := neoism.CypherQuery{
			Statement: `MATCH (url:Url) RETURN url`,
			Result:    &urls,
		}
		err := neo.Cypher(&cq)
		if err != nil {
			printer.JSON(w, http.StatusServiceUnavailable, map[string]interface{}{
				"code":    http.StatusServiceUnavailable,
				"error":   http.StatusText(http.StatusServiceUnavailable),
				"message": err,
			})
		}
		printer.JSON(w, http.StatusOK, map[string][]Url{"urls": urls})
	}
}
Ejemplo n.º 6
0
func getUserTickets(res *[]struct {
	A string `json:"n.COUPON_ID"`
}, id string) error {
	database, err := neoism.Connect("http://*****:*****@localhost:7474/db/data")

	if err != nil {
		fmt.Printf("NEO4J Connection FAILED\n")
		return err
	}

	cq := neoism.CypherQuery{
		Statement: `
			MATCH (n:Ticket)
			WHERE n.ID = {user_id}
			RETURN n.COUPON_ID
		`,
		Parameters: neoism.Props{"user_id": id},
		Result:     &res,
	}
	err = database.Cypher(&cq)
	if err != nil {
		fmt.Printf("Error Cyphering To Database\n")
		return err
	}

	return nil
}
Ejemplo n.º 7
0
func RemoveCoupon(coupon util.GetCoupon_struct) (string, error){
	fmt.Printf("Accessing NEO4J Server Cyphering RemoveCoupon\n")
	database, err := neoism.Connect("http://*****:*****@localhost:7474/db/data")
	
	if err != nil {
		fmt.Printf("NEO4J Connection FAILED\n")
		return "Internal Service Error", err	
	}
	
	cq := neoism.CypherQuery{
    Statement: `
    	MATCH (n:Coupon)
      	WHERE n.ID = {user_id} AND n.COUPON_ID = {coupon_id} 
       	DELETE n
    `,
    Parameters: neoism.Props{"user_id": coupon.ID, "coupon_id": coupon.COUPON_ID},
	}
	err = database.Cypher(&cq)
	if err != nil {
		fmt.Printf("Error Cyphering To Database\n")
		return "Internal Service Error", err
	}

	return "Success", nil
}
Ejemplo n.º 8
0
func UpdateBusinessGeneral(update util.UpdateGeneralBusiness_struct) (string, error) {
	fmt.Printf("Accessing NEO4J Server: Cyphering UpdateBusinessGeneral\n")

	database, err := neoism.Connect("http://*****:*****@localhost:7474/db/data")

	if err != nil {
		fmt.Printf("NEO4J Connection FAILED\n")
		return "Internal Service Error", err
	}

	res := []struct {
		A string `json:"n.NAME"`
	}{}

	res2 := []struct {
		A string `json:"n.NAME"`
	}{}

	cq := neoism.CypherQuery{
		Statement: `
        	MATCH (n:Activity)
       		WHERE n.ID = {user_id}
			SET n.NAME = {name}, n.MIN_AGE = {min_age}, n.MAX_AGE = {max_age}, n.MIN_PEOPLE = {min_people},
									n.MAX_PEOPLE = {max_people}, n.MAIN_CATEGORY = {main_category}, n.SUB_CATEGORY = {sub_category}
        	RETURN n.NAME
    	`,
		Parameters: neoism.Props{"user_id": update.ID, "name": update.NAME, "min_age": update.MIN_AGE,
			"max_age": update.MAX_AGE, "min_people": update.MIN_PEOPLE, "max_people": update.MAX_PEOPLE,
			"main_category": update.MAIN_CATEGORY, "sub_category": update.SUB_CATEGORY},
		Result: &res,
	}

	err = database.Cypher(&cq)
	if err != nil {
		fmt.Printf("Error Cyphering To Database\n")
		return "Internal Service Error", err
	}

	cq = neoism.CypherQuery{
		Statement: `
        	MATCH (n:Coupon)
       		WHERE n.ID = {user_id}
        	SET	n.NAME = {name}
			RETURN n.NAME
    	`,
		Parameters: neoism.Props{"user_id": update.ID, "name": update.NAME},
		Result:     &res2,
	}
	err = database.Cypher(&cq)
	if err != nil {
		fmt.Printf("Error Cyphering To Database\n")
		return "Internal Service Error", err
	}

	if len(res) == 1 && len(res2) == 1 {
		return "Success", nil
	}

	return "Error: User Not Found", nil
}
Ejemplo n.º 9
0
func FindCoupon(id string) (bool, error) {
	database, err := neoism.Connect("http://*****:*****@localhost:7474/db/data")

	if err != nil {
		fmt.Printf("NEO4J Connection FAILED\n")
		return false, err
	}

	res := []struct {
		A string `json:"n.ID"`
	}{}

	cq := neoism.CypherQuery{
		Statement: `
        	MATCH (n:Coupon)
       		WHERE n.COUPON_ID = {id}
        	RETURN n.ID
    	`,
		Parameters: neoism.Props{"id": id},
		Result:     &res,
	}

	err = database.Cypher(&cq)
	if err != nil {
		fmt.Printf("Error Cyphering To Database\n")
		return false, err
	}

	if len(res) == 0 {
		return false, nil
	}

	return true, nil
}
Ejemplo n.º 10
0
func LoginBusiness(login Util.Login_struct) (string, error) {
	fmt.Printf("Accessing NEO4J Server Cyphering BusinessLogin\n")
	database, err := neoism.Connect("http://*****:*****@localhost:7474/db/data")

	if err != nil {
		fmt.Printf("NEO4J Connection FAILED\n")
		return "Internal Service Error", err
	}

	res := []struct {
		A string `json:"n.USER_ID"`
	}{}

	cq := neoism.CypherQuery{
		Statement: `
        	MATCH (n:Business)
       		WHERE n.USER_ID = {user_id} AND n.PASSWORD = {password}
        	RETURN n.USER_ID
    	`,
		Parameters: neoism.Props{"user_id": login.ID, "password": login.PASSWORD},
		Result:     &res,
	}
	err = database.Cypher(&cq)
	if err != nil {
		fmt.Printf("Error Cyphering To Database\n")
		return "Internal Service Error", err
	}

	if len(res) == 1 {
		return "Success", nil
	}

	fmt.Printf("Business User Login Failed\n")
	return "Failed", nil
}
Ejemplo n.º 11
0
Archivo: neo.go Proyecto: vly/ssdir
func (db *Database) Connect(hostname string) (database *neoism.Database, ok int) {
	database, err := neoism.Connect("http://127.0.0.1:7474/db/data")
	if err != nil {
		log.Fatal(err)
	}
	db.db = database
	return
}
Ejemplo n.º 12
0
func init() {
	resetDB()
	var err error
	db, err = neoism.Connect("http://localhost:7474/db/data")
	if err != nil {
		panic(err)
	}
}
Ejemplo n.º 13
0
func GetActiveCoupons(coupon util.GetCoupon_struct) (string, error){
	fmt.Printf("Accessing NEO4J Server Cyphering GetActiveCoupon\n")
	database, err := neoism.Connect("http://*****:*****@localhost:7474/db/data")
	
	if err != nil {
		fmt.Printf("NEO4J Connection FAILED\n")
		return "Internal Service Error", err	
	}
	
	res := []struct {
		N neoism.Node 
    }{}

	cq := neoism.CypherQuery{
    Statement: `
    	MATCH (n:Coupon)
      	WHERE n.ID = {user_id} AND n.VALID = "TRUE"
       	RETURN n
    `,
    Parameters: neoism.Props{"user_id": coupon.ID},
    Result:     &res,
	}
	err = database.Cypher(&cq)
	if err != nil {
		fmt.Printf("Error Cyphering To Database\n")
		return "Internal Service Error", err
	}

	response := ""
	data := map[string]interface{}{}
	if len(res) != 0 {
		jsonString := "{\"coupons\": ["
		for i:=0; i < len(res); i++ {
			coupon, err := json.Marshal(res[i].N.Data)
			if err != nil {
				fmt.Printf("%s\n", err)
			}	
			jsonString += string(coupon)
			if i != (len(res)-1){
				jsonString += ","
			}
		}
		jsonString += "]}"

		dec := json.NewDecoder(strings.NewReader(jsonString))
		dec.Decode(&data)
		
		coupons, err := json.Marshal(data)
		if err != nil {
			fmt.Printf("%s\n", err)
		}
		response = string(coupons)
			
		return response, nil
	}

	return "No Active Coupons", nil
}
Ejemplo n.º 14
0
func UpdateBusinessAddress(update util.UpdateAddressBusiness_struct) (string, error) {
	fmt.Printf("Accessing NEO4J Server: Cyphering UpdateBusinessAddress\n")

	database, err := neoism.Connect("http://*****:*****@localhost:7474/db/data")

	if err != nil {
		fmt.Printf("NEO4J Connection FAILED\n")
		return "Internal Service Error", err
	}

	res := []struct {
		A string `json:"n.NAME"`
	}{}

	res2 := []struct {
		A string `json:"n.NAME"`
	}{}

	cq := neoism.CypherQuery{
		Statement: `
        	MATCH (n:Activity)
       		WHERE n.ID = {user_id}
        	SET n.ADDRESS = {address}, n.TOWNSHIP = {township}, n.CAMPUS = {campus}
			RETURN n.NAME
    	`,
		Parameters: neoism.Props{"user_id": update.ID, "address": update.ADDRESS, "township": update.TOWNSHIP, "campus": update.CAMPUS},
		Result:     &res,
	}

	err = database.Cypher(&cq)
	if err != nil {
		fmt.Printf("Error Cyphering To Database\n")
		return "Internal Service Error", err
	}

	cq = neoism.CypherQuery{
		Statement: `
        	MATCH (n:Coupon)
       		WHERE n.ID = {user_id}
        	SET n.ADDRESS = {address}, n.CAMPUS = {campus}
			RETURN n.NAME
    	`,
		Parameters: neoism.Props{"user_id": update.ID, "address": update.ADDRESS, "campus": update.CAMPUS},
		Result:     &res2,
	}

	err = database.Cypher(&cq)
	if err != nil {
		fmt.Printf("Error Cyphering To Database\n")
		return "Internal Service Error", err
	}

	if len(res) == 1 && len(res2) == 1 {
		return "Success", nil
	}

	return "Error: User Not Found", nil
}
Ejemplo n.º 15
0
func main() {
	neo, err := neoism.Connect(os.Getenv("GRAPHENEDB_URL"))
	if err != nil {
		fmt.Println(err)
		return
	}

	createUrls(neo)
}
Ejemplo n.º 16
0
// Constructor, use this when creating a new Query struct.
func NewQuery(uri string) *Query {
	neo4jdb, err := neoism.Connect(uri)
	panicIfErr(err)

	query := Query{neo4jdb}
	query.DatabaseInit()

	return &query
}
Ejemplo n.º 17
0
func Cleanup() {
	db, _ := neoism.Connect("http://*****:*****@localhost:7474")
	cq := neoism.CypherQuery{
		Statement: `MATCH (n) OPTIONAL MATCH (n)-[r]-() DELETE n,r`,
	}
	if err := db.Cypher(&cq); err != nil {
		panic(err)
	}
}
Ejemplo n.º 18
0
func connect(app *App) {
	url := app.Config.Neo4JUrl
	var db *neoism.Database
	db, err := neoism.Connect(url)
	if err != nil {
		log.Fatal("Could not connect to DB", err)
	}
	app.GraphDB = db
}
Ejemplo n.º 19
0
func main() {
	flag.Parse()

	numCpus := runtime.NumCPU()
	prevProcs := runtime.GOMAXPROCS(*threads)
	glog.WithField("num_cpu", numCpus).
		WithField("threads", *threads).
		WithField("prev_maxprocs", prevProcs).
		Info("Set max procs to threads")

	if len(*rdfGzips) == 0 {
		glog.Fatal("No RDF GZIP files specified")
	}

	db, err := neoism.Connect("http://localhost:7474/db/data")
	if err != nil {
		log.Fatal(err)
	}

	files := strings.Split(*rdfGzips, ",")
	for _, path := range files {
		if len(path) == 0 {
			continue
		}
		glog.WithField("path", path).Info("Handling...")
		f, err := os.Open(path)
		if err != nil {
			glog.WithError(err).Fatal("Unable to open rdf file.")
		}

		r, err := gzip.NewReader(f)
		if err != nil {
			glog.WithError(err).Fatal("Unable to create gzip reader.")
		}

		count, err := HandleRdfReader(db, r, *mod)
		if err != nil {
			glog.WithError(err).Fatal("While handling rdf reader.")
		}
		glog.WithField("count", count).Info("RDFs parsed")

		r.Close()
		f.Close()
	}

	p := neoism.Props{"_xid_": 10}
	n, created, err := db.GetOrCreateNode("Entity", "_xid_", p)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("Created", created)
	p, err = n.Properties()
	fmt.Println(n.Id(), p, err)
}
Ejemplo n.º 20
0
func initdb() {
	//neoism.Connect("http://*****:*****@server:port")
	var err error
	db, err = neoism.Connect("http://*****:*****@carsimulator.sb05.stations.graphenedb.com:24789")
	//If error connecting to database, halt execution and display error message
	if err != nil {
		panic(err)
	}
	if db == nil {
		panic("Database object is null")
	}
}
Ejemplo n.º 21
0
func UpdateUserStudent(update util.Student_struct) (string, error) {
	fmt.Printf("Accessing NEO4J Server: Cyphering UpdateUserStudent\n")

	database, err := neoism.Connect("http://*****:*****@localhost:7474/db/data")

	if err != nil {
		fmt.Printf("NEO4J Connection FAILED\n")
		return "Internal Service Error", err
	}

	res := []struct {
		A string `json:"n.RUID"`
	}{}

	cq := neoism.CypherQuery{
		Statement: `
		 	MATCH (n:Student)
			WHERE n.USER_ID = {user_id}
			SET n.RUID = {ruid}, n.DEGREE = {degree}, n.CAMPUS = {campus}, n.YEAR = {year}
		 	RETURN n.ruid
		`,
		Parameters: neoism.Props{"user_id": update.ID, "ruid": update.RUID, "degree": update.DEGREE,
			"campus": update.CAMPUS, "year": update.YEAR},
		Result: &res,
	}

	err = database.Cypher(&cq)
	if err != nil {
		fmt.Printf("Error Cyphering To Database\n")
		return "Internal Service Error", err
	}

	if len(res) == 1 {
		return "Success", nil
	} else {
		cq := neoism.CypherQuery{
			Statement: `
		 	CREATE (n:Student {USER_ID: {user_id}, RUID: {ruid}, DEGREE: {degree}, CAMPUS: {campus}, YEAR: {year}})
		`,
			Parameters: neoism.Props{"user_id": update.ID, "ruid": update.RUID, "degree": update.DEGREE,
				"campus": update.CAMPUS, "year": update.YEAR},
			Result: &res,
		}

		err = database.Cypher(&cq)
		if err != nil {
			fmt.Printf("Error Cyphering To Database\n")
			return "Internal Service Error", err
		}

		return "Success", nil
	}
}
Ejemplo n.º 22
0
func (m *TaxonomyEngine) Start() {

	db, err := neoism.Connect("http://*****:*****@localhost:7474/db/data/")
	if err != nil {
		fmt.Println("error in setup, db is:", db)
		panic(err)
	}

	m.db = db

	m.cache.Setup()
}
Ejemplo n.º 23
0
func CreateNewConnection(specialLabel ...string) Connection {
	log.Println("Trying to connect database...")
	//http://your_user:[email protected]/db/data/
	//	dbpath := "http://*****:*****@localhost:7474/db/data"
	dbpath := "http://*****:*****@localhost:7474/db/data"
	db, err := neoism.Connect(dbpath)
	utils.HandleError(err)

	c := NewConnectionNeo(dbpath, db, specialLabel...)
	return Connection(&c)

}
Ejemplo n.º 24
0
func main() {

	neoUrl := os.Getenv("NEO_URL")
	if neoUrl == "" {
		log.Println("no $NEO_URL set, defaulting to local")
		neoUrl = "http://localhost:7474/db/data"
	}
	log.Printf("connecting to %s\n", neoUrl)

	var err error
	db, err = neoism.Connect(neoUrl)
	if err != nil {
		panic(err)
	}

	ensureIndexes(db)

	writeQueue = make(chan organisation, 2048)

	port := 8080

	m := mux.NewRouter()
	http.Handle("/", m)

	m.HandleFunc("/organisations/{uuid}", idWriteHandler).Methods("PUT")
	m.HandleFunc("/organisations/", allWriteHandler).Methods("PUT")

	go func() {
		log.Printf("listening on %d", port)
		if err := http.ListenAndServe(fmt.Sprintf(":%d", port), nil); err != nil {
			log.Printf("web stuff failed: %v\n", err)
		}
	}()

	var wg sync.WaitGroup

	wg.Add(1)
	go func() {
		orgWriteLoop()
		wg.Done()
	}()

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)

	// wait for ctrl-c
	<-c
	close(writeQueue)
	wg.Wait()
	println("exiting")

}
Ejemplo n.º 25
0
func CreateTicket(tickets util.Ticket_struct) (string, error) {
	fmt.Printf("Accessing NEO4J Server Cyphering CreateTicket\n")
	database, err := neoism.Connect("http://*****:*****@localhost:7474/db/data")

	if err != nil {
		fmt.Printf("NEO4J Connection FAILED\n")
		return "Internal Service Error", err
	}

	res := []struct {
		A string `json:"n.ID"`
	}{}

	cq := neoism.CypherQuery{
		Statement: `
    	MATCH (n:Ticket)
      	WHERE n.ID = {user_id} AND n.VALID = "TRUE"
       	RETURN n.ID
    `,
		Parameters: neoism.Props{"user_id": tickets.ID},
		Result:     &res,
	}
	err = database.Cypher(&cq)
	if err != nil {
		fmt.Printf("Error Cyphering To Database\n")
		return "Internal Service Error", err
	}

	if len(res) < 3 {
		cq = neoism.CypherQuery{
			Statement: `
			CREATE (n:Ticket {ID: {user_id},
						COUPON_ID: {id},
						VALID: "TRUE"
				})
		`,
			Parameters: neoism.Props{"user_id": tickets.ID,
				"id": tickets.COUPON_ID},
		}

		err = database.Cypher(&cq)
		if err != nil {
			fmt.Printf("Error Cyphering To Database\n")
			return "Internal Service Error", err
		}

		return "Success", nil
	} else {
		fmt.Printf("User Reached Max Tickets\n")
		return "Max Active Tickets Reached", nil
	}
}
Ejemplo n.º 26
0
Archivo: db.go Proyecto: halk/in-common
// GetGraph returns a connected neoism.Database
func GetGraph() *neoism.Database {
	dsn := os.Getenv("IN_COMMON_NEO4J_DSN")
	if dsn == "" {
		dsn = "http://*****:*****@localhost:7474/db/data"
	}

	db, err := neoism.Connect(dsn)
	if err != nil {
		panic(err)
	}

	return db
}
Ejemplo n.º 27
0
func initdb() {
	var err error

	//neoism.Connect("http://*****:*****@server:port")
	panic("This script works on the default example films and actors database, you will need that running on localhost. Put your password in the Connect statement below then comment out this panic line. The default user is neo4j")

	db, err = neoism.Connect("http://*****:*****@localhost:7474/")
	if err != nil {
		panic(err)
	}
	if db == nil {
		panic("Database object is null")
	}
}
Ejemplo n.º 28
0
func getCouponsFromMatchs(business []struct {
	A string `json:"n.ID"`
}) (string, int, error) {
	database, err := neoism.Connect("http://*****:*****@localhost:7474/db/data")

	if err != nil {
		fmt.Printf("NEO4J Connection FAILED\n")
		return "", 0, err
	}

	coupon := []struct {
		A string `json:"n.COUPON_ID"`
	}{}

	size := 0
	coupons := ""
	for i := 0; i < len(business); i++ {
		id := business[i].A

		cq := neoism.CypherQuery{
			Statement: `
			MATCH (n:Coupon)
			WHERE n.ID = {user_id} AND n.VALID = "TRUE"
			RETURN n.COUPON_ID
		`,
			Parameters: neoism.Props{"user_id": id},
			Result:     &coupon,
		}
		err = database.Cypher(&cq)
		if err != nil {
			fmt.Printf("Error Cyphering To Database\n")
			return "", 0, err
		}

		if i > 0 && len(coupon) != 0 {
			coupons += ","
		}

		for x := 0; x < len(coupon); x++ {
			size++
			coupons += coupon[x].A
			if x != (len(coupon) - 1) {
				coupons += ","
			}
		}
	}

	return coupons, size, nil
}
Ejemplo n.º 29
0
// creates a new driver with the unique set of config options specified in the config file
func newDriver(c *backend.Config) (backend.Graph, error) {

	url := fmt.Sprintf(
		"http://%s:%s@%s:%d",
		c.StringKey("user"),
		c.StringKey("password"),
		c.StringKey("host"),
		c.IntKey("port"),
	)

	//	db, err := sql.Open("neo4j-cypher", url)
	db, err := neoism.Connect(url)
	return &Driver{
		Connection: db,
	}, err
}
Ejemplo n.º 30
0
Archivo: web.go Proyecto: fiatjaf/nodes
func main() {
	var err error
	db, err = neoism.Connect(os.Getenv("NEO4J_URL"))
	if err != nil {
		log.Fatal(err)
	}

	// middleware
	middle := interpose.New()
	middle.Use(adaptors.FromNegroni(cors.New(cors.Options{
		// CORS
		AllowedOrigins: []string{"*"},
	})))

	// router
	router := mux.NewRouter()
	router.StrictSlash(true) // redirects '/path' to '/path/'
	middle.UseHandler(router)
	// ~

	// > routes
	router.HandleFunc("/rel/", func(w http.ResponseWriter, r *http.Request) {
		handlers.CreateRelationship(db, w, r)
	}).Methods("POST")
	router.HandleFunc("/eql/", func(w http.ResponseWriter, r *http.Request) {
		handlers.CreateEquality(db, w, r)
	}).Methods("POST")
	router.HandleFunc("/btw/", func(w http.ResponseWriter, r *http.Request) {
		handlers.RelationshipsBetween(db, w, r)
	}).Methods("GET")
	router.HandleFunc("/cluster.svg", func(w http.ResponseWriter, r *http.Request) {
		handlers.ViewRelationships(db, w, r)
	}).Methods("GET")
	// ~

	// static files
	router.PathPrefix("/").Handler(http.FileServer(http.Dir("./static/")))
	// ~

	port := os.Getenv("PORT")
	if port == "" {
		port = "5000"
	}
	log.Print("listening...")
	http.ListenAndServe(":"+port, middle)
}