summary refs log tree commit diff stats
path: root/svc/svc.go
blob: a7786d9749e53a452fb801882228572dcd713722 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package svc // import "github.com/getwtxt/getwtxt/svc"

import (
	"fmt"
	"log"
	"net/http"
	"time"

	"github.com/gorilla/handlers"
	"github.com/gorilla/mux"
)

// Start is the initialization function for getwtxt
func Start() {
	before := time.Now()
	initSvc()

	// StrictSlash(true) allows /api and /api/
	// to serve the same content without duplicating
	// handlers/paths
	index := mux.NewRouter().StrictSlash(true)
	setIndexRouting(index)
	api := index.PathPrefix("/api").Subrouter()
	setEndpointRouting(api)

	confObj.Mu.RLock()
	portnum := fmt.Sprintf(":%v", confObj.Port)
	if !confObj.IsProxied {
		index.Host(confObj.Instance.URL)
	}
	TLS := confObj.TLS.Use
	TLSCert := confObj.TLS.Cert
	TLSKey := confObj.TLS.Key
	confObj.Mu.RUnlock()

	server := newServer(portnum, index)
	log.Printf("*** Listening on %v\n", portnum)
	log.Printf("*** getwtxt %v Startup finished at %v, took %v\n\n", Vers, time.Now().Format(time.RFC3339), time.Since(before))

	if TLS {
		errLog("", server.ListenAndServeTLS(TLSCert, TLSKey))
	} else {
		errLog("", server.ListenAndServe())
	}

	closeLog <- true
	killTickers()
	killDB()
	close(dbChan)
	close(closeLog)
}

func newServer(port string, index *mux.Router) *http.Server {
	// handlers.CompressHandler gzips all responses.
	// ipMiddleware passes the request IP along.
	// Write/Read timeouts are self explanatory.
	return &http.Server{
		Handler:      handlers.CompressHandler(ipMiddleware(index)),
		Addr:         port,
		WriteTimeout: 15 * time.Second,
		ReadTimeout:  15 * time.Second,
	}
}

func setIndexRouting(index *mux.Router) {
	index.Path("/").
		Methods("GET", "HEAD").
		HandlerFunc(staticHandler)
	index.Path("/css").
		Methods("GET", "HEAD").
		HandlerFunc(staticHandler)
	index.Path("/api").
		Methods("GET", "HEAD").
		HandlerFunc(apiBaseHandler)
}

func setEndpointRouting(api *mux.Router) {
	// twtxt will add support for other formats later.
	// Maybe json? Making this future-proof.
	api.Path("/{format:(?:plain)}").
		Methods("GET", "HEAD").
		HandlerFunc(apiFormatHandler)

	// Non-standard API call to list *all* tweets
	// in a single request.
	api.Path("/{format:(?:plain)}/tweets/all").
		Methods("GET", "HEAD").
		HandlerFunc(apiAllTweetsHandler)

	// Specifying the endpoint with and without query information.
	// Will return 404 on empty queries otherwise.
	api.Path("/{format:(?:plain)}/{endpoint:(?:mentions|users|tweets)}").
		Methods("GET", "HEAD").
		HandlerFunc(apiEndpointHandler)
	api.Path("/{format:(?:plain)}/{endpoint:(?:mentions|users|tweets)}").
		Queries("url", "{url}", "q", "{query}", "page", "{[0-9]+}").
		Methods("GET", "HEAD").
		HandlerFunc(apiEndpointHandler)

	// This is for submitting new users. Both query variables must exist
	// in the request for this to match.
	api.Path("/{format:(?:plain)}/{endpoint:users}").
		Queries("url", "{url}", "nickname", "{nickname:[a-zA-Z0-9_-]+}").
		Methods("POST").
		HandlerFunc(apiEndpointPOSTHandler)
	// This is for submitting new users incorrectly
	// and letting the requester know about their error.
	api.Path("/{format:(?:plain)}/{endpoint:users}").
		Queries("url", "{url}").
		Methods("POST").
		HandlerFunc(apiEndpointPOSTHandler)
	// This is also for submitting new users incorrectly
	// and letting the requester know about their error.
	api.Path("/{format:(?:plain)}/{endpoint:users}").
		Queries("nickname", "{nickname:[a-zA-Z0-9_-]+}").
		Methods("POST").
		HandlerFunc(apiEndpointPOSTHandler)

	// Show all observed tags
	api.Path("/{format:(?:plain)}/tags").
		Methods("GET", "HEAD").
		HandlerFunc(apiTagsBaseHandler)
	// Show Nth page of all observed tags
	api.Path("/{format:(?:plain)}/tags").
		Queries("page", "{[0-9]+}").
		Methods("GET", "HEAD").
		HandlerFunc(apiTagsBaseHandler)

	// Requests statuses with a specific tag
	api.Path("/{format:(?:plain)}/tags/{tags:[a-zA-Z0-9_-]+}").
		Methods("GET", "HEAD").
		HandlerFunc(apiTagsHandler)
	// Requests Nth page of statuses with a specific tag
	api.Path("/{format:(?:plain)}/tags/{tags:[a-zA-Z0-9_-]+}").
		Queries("page", "{[0-9]+}").
		Methods("GET", "HEAD").
		HandlerFunc(apiTagsHandler)
}
malloc(sizeof(Bookmark)); bm2->barejid = strdup("room2@conf.org"); bm2->nick = strdup("steve"); bm2->autojoin = TRUE; Bookmark *bm3 = malloc(sizeof(Bookmark)); bm3->barejid = strdup("room3@conf.org"); bm3->nick = strdup("dave"); bm3->autojoin = TRUE; Bookmark *bm4 = malloc(sizeof(Bookmark)); bm4->barejid = strdup("room4@conf.org"); bm4->nick = strdup("james"); bm4->autojoin = FALSE; Bookmark *bm5 = malloc(sizeof(Bookmark)); bm5->barejid = strdup("room5@conf.org"); bm5->nick = strdup("mike"); bm5->autojoin = FALSE; bookmarks = g_list_append(bookmarks, bm1); bookmarks = g_list_append(bookmarks, bm2); bookmarks = g_list_append(bookmarks, bm3); bookmarks = g_list_append(bookmarks, bm4); bookmarks = g_list_append(bookmarks, bm5); will_return(connection_get_status, JABBER_CONNECTED); will_return(bookmark_get_list, bookmarks); // TODO - Custom list compare glist_set_cmp((GCompareFunc)_cmp_bookmark); expect_any(cons_show_bookmarks, list); gboolean result = cmd_bookmark(&window, CMD_BOOKMARK, args); assert_true(result); free(bm1->barejid); free(bm1->nick); free(bm1); free(bm2->barejid); free(bm2->nick); free(bm2); free(bm3->barejid); free(bm3->nick); free(bm3); free(bm4->barejid); free(bm4->nick); free(bm4); free(bm5->barejid); free(bm5->nick); free(bm5); } void cmd_bookmark_add_shows_message_when_invalid_jid(void **state) { char *jid = "room"; gchar *args[] = { "add", jid, NULL }; ProfWin window; window.type = WIN_CONSOLE; will_return(connection_get_status, JABBER_CONNECTED); expect_cons_show("Invalid room, must be of the form room@domain.tld"); expect_cons_show(""); gboolean result = cmd_bookmark(&window, CMD_BOOKMARK, args); assert_true(result); } void cmd_bookmark_add_adds_bookmark_with_jid(void **state) { char *jid = "room@conf.server"; gchar *args[] = { "add", jid, NULL }; ProfWin window; window.type = WIN_CONSOLE; will_return(connection_get_status, JABBER_CONNECTED); expect_string(bookmark_add, jid, jid); expect_any(bookmark_add, nick); expect_any(bookmark_add, password); expect_any(bookmark_add, autojoin_str); will_return(bookmark_add, TRUE); expect_cons_show("Bookmark added for room@conf.server."); gboolean result = cmd_bookmark(&window, CMD_BOOKMARK, args); assert_true(result); } void cmd_bookmark_uses_roomjid_in_room(void **state) { muc_init(); gchar *args[] = { NULL }; ProfMucWin muc_win; muc_win.window.type = WIN_MUC; muc_win.memcheck = PROFMUCWIN_MEMCHECK; muc_win.roomjid = "room@conf.server"; will_return(connection_get_status, JABBER_CONNECTED); expect_string(bookmark_add, jid, muc_win.roomjid); expect_any(bookmark_add, nick); expect_any(bookmark_add, password); expect_any(bookmark_add, autojoin_str); will_return(bookmark_add, TRUE); expect_win_println("Bookmark added for room@conf.server."); gboolean result = cmd_bookmark(&muc_win.window, CMD_BOOKMARK, args); assert_true(result); muc_close(); } void cmd_bookmark_add_uses_roomjid_in_room(void **state) { muc_init(); gchar *args[] = { "add", NULL }; ProfMucWin muc_win; muc_win.window.type = WIN_MUC; muc_win.memcheck = PROFMUCWIN_MEMCHECK; muc_win.roomjid = "room@conf.server"; will_return(connection_get_status, JABBER_CONNECTED); expect_string(bookmark_add, jid, muc_win.roomjid); expect_any(bookmark_add, nick); expect_any(bookmark_add, password); expect_any(bookmark_add, autojoin_str); will_return(bookmark_add, TRUE); expect_win_println("Bookmark added for room@conf.server."); gboolean result = cmd_bookmark(&muc_win.window, CMD_BOOKMARK, args); assert_true(result); muc_close(); } void cmd_bookmark_add_uses_supplied_jid_in_room(void **state) { muc_init(); char *jid = "room1@conf.server"; gchar *args[] = { "add", jid, NULL }; ProfMucWin muc_win; muc_win.window.type = WIN_MUC; muc_win.memcheck = PROFMUCWIN_MEMCHECK; muc_win.roomjid = "room2@conf.server"; will_return(connection_get_status, JABBER_CONNECTED); expect_string(bookmark_add, jid, jid); expect_any(bookmark_add, nick); expect_any(bookmark_add, password); expect_any(bookmark_add, autojoin_str); will_return(bookmark_add, TRUE); expect_cons_show("Bookmark added for room1@conf.server."); gboolean result = cmd_bookmark(&muc_win.window, CMD_BOOKMARK, args); assert_true(result); muc_close(); } void cmd_bookmark_add_adds_bookmark_with_jid_nick(void **state) { char *jid = "room@conf.server"; char *nick = "bob"; gchar *args[] = { "add", jid, "nick", nick, NULL }; ProfWin window; window.type = WIN_CONSOLE; will_return(connection_get_status, JABBER_CONNECTED); expect_string(bookmark_add, jid, jid); expect_string(bookmark_add, nick, nick); expect_any(bookmark_add, password); expect_any(bookmark_add, autojoin_str); will_return(bookmark_add, TRUE); expect_cons_show("Bookmark added for room@conf.server."); gboolean result = cmd_bookmark(&window, CMD_BOOKMARK, args); assert_true(result); } void cmd_bookmark_add_adds_bookmark_with_jid_autojoin(void **state) { char *jid = "room@conf.server"; gchar *args[] = { "add", jid, "autojoin", "on", NULL }; ProfWin window; window.type = WIN_CONSOLE; will_return(connection_get_status, JABBER_CONNECTED); expect_string(bookmark_add, jid, jid); expect_any(bookmark_add, nick); expect_any(bookmark_add, password); expect_string(bookmark_add, autojoin_str, "on"); will_return(bookmark_add, TRUE); expect_cons_show("Bookmark added for room@conf.server."); gboolean result = cmd_bookmark(&window, CMD_BOOKMARK, args); assert_true(result); } void cmd_bookmark_add_adds_bookmark_with_jid_nick_autojoin(void **state) { char *jid = "room@conf.server"; char *nick = "bob"; gchar *args[] = { "add", jid, "nick", nick, "autojoin", "on", NULL }; ProfWin window; window.type = WIN_CONSOLE; will_return(connection_get_status, JABBER_CONNECTED); expect_string(bookmark_add, jid, jid); expect_string(bookmark_add, nick, nick); expect_any(bookmark_add, password); expect_string(bookmark_add, autojoin_str, "on"); will_return(bookmark_add, TRUE); expect_cons_show("Bookmark added for room@conf.server."); gboolean result = cmd_bookmark(&window, CMD_BOOKMARK, args); assert_true(result); } void cmd_bookmark_remove_removes_bookmark(void **state) { char *jid = "room@conf.server"; gchar *args[] = { "remove", jid, NULL }; ProfWin window; window.type = WIN_CONSOLE; will_return(connection_get_status, JABBER_CONNECTED); expect_string(bookmark_remove, jid, jid); will_return(bookmark_remove, TRUE); expect_cons_show("Bookmark removed for room@conf.server."); gboolean result = cmd_bookmark(&window, CMD_BOOKMARK, args); assert_true(result); } void cmd_bookmark_remove_shows_message_when_no_bookmark(void **state) { char *jid = "room@conf.server"; gchar *args[] = { "remove", jid, NULL }; ProfWin window; window.type = WIN_CONSOLE; will_return(connection_get_status, JABBER_CONNECTED); expect_any(bookmark_remove, jid); will_return(bookmark_remove, FALSE); expect_cons_show("No bookmark exists for room@conf.server."); gboolean result = cmd_bookmark(&window, CMD_BOOKMARK, args); assert_true(result); } void cmd_bookmark_remove_uses_roomjid_in_room(void **state) { muc_init(); gchar *args[] = { "remove", NULL }; ProfMucWin muc_win; muc_win.window.type = WIN_MUC; muc_win.memcheck = PROFMUCWIN_MEMCHECK; muc_win.roomjid = "room@conf.server"; will_return(connection_get_status, JABBER_CONNECTED); expect_string(bookmark_remove, jid, muc_win.roomjid); will_return(bookmark_remove, TRUE); expect_win_println("Bookmark removed for room@conf.server."); gboolean result = cmd_bookmark(&muc_win.window, CMD_BOOKMARK, args); assert_true(result); muc_close(); } void cmd_bookmark_remove_uses_supplied_jid_in_room(void **state) { muc_init(); char *jid = "room1@conf.server"; gchar *args[] = { "remove", jid, NULL }; ProfMucWin muc_win; muc_win.window.type = WIN_MUC; muc_win.memcheck = PROFMUCWIN_MEMCHECK; muc_win.roomjid = "room2@conf.server"; will_return(connection_get_status, JABBER_CONNECTED); expect_string(bookmark_remove, jid, jid); will_return(bookmark_remove, TRUE); expect_cons_show("Bookmark removed for room1@conf.server."); gboolean result = cmd_bookmark(&muc_win.window, CMD_BOOKMARK, args); assert_true(result); muc_close(); }