/
http.dm
129 lines (110 loc) · 4.61 KB
/
http.dm
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
SUBSYSTEM_DEF(http)
name = "HTTP"
flags = SS_TICKER | SS_BACKGROUND // Measure in ticks, but also only run if we have the spare CPU. We also dont init.
wait = 1
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY // All the time
// Assuming for the worst, since only discord is hooked into this for now, but that may change
offline_implications = "The server is no longer capable of making async HTTP requests. Shuttle call recommended."
/// List of all async HTTP requests in the processing chain
var/list/datum/http_request/active_async_requests
/// Variable to define if logging is enabled or not. Disabled by default since we know the requests the server is making. Enable with VV if you need to debug requests
var/logging_enabled = FALSE
/// Total requests the SS has processed in a round
var/total_requests
/datum/controller/subsystem/http/PreInit()
. = ..()
rustg_create_async_http_client() // Open the door
/datum/controller/subsystem/http/Initialize(start_timeofday)
active_async_requests = list()
return ..()
/datum/controller/subsystem/http/get_stat_details()
return "P: [length(active_async_requests)] | T: [total_requests]"
/datum/controller/subsystem/http/fire(resumed)
for(var/r in active_async_requests)
var/datum/http_request/req = r
// Check if we are complete
if(req.is_complete())
// If so, take it out the processing list
active_async_requests -= req
var/datum/http_response/res = req.into_response()
// If the request has a callback, invoke it.Async of course to avoid choking the SS
if(req.cb)
req.cb.InvokeAsync(res)
// And log the result
if(logging_enabled)
var/list/log_data = list()
log_data += "BEGIN ASYNC RESPONSE (ID: [req.id])"
if(res.errored)
log_data += "\t ----- RESPONSE ERRROR -----"
log_data += "\t [res.error]"
else
log_data += "\tResponse status code: [res.status_code]"
log_data += "\tResponse body: [res.body]"
log_data += "\tResponse headers: [json_encode(res.headers)]"
log_data += "END ASYNC RESPONSE (ID: [req.id])"
rustg_log_write(GLOB.http_log, log_data.Join("\n[GLOB.log_end]"))
/**
* Async request creator
*
* Generates an async request, and adds it to the subsystem's processing list
* These should be used as they do not lock the entire DD process up as they execute inside their own thread pool inside RUSTG
*/
/datum/controller/subsystem/http/proc/create_async_request(method, url, body = "", list/headers, datum/callback/proc_callback)
var/datum/http_request/req = new()
req.prepare(method, url, body, headers)
if(proc_callback)
req.cb = proc_callback
// Begin it and add it to the SS active list
req.begin_async()
active_async_requests += req
total_requests++
if(logging_enabled)
// Create a log holder
var/list/log_data = list()
log_data += "BEGIN ASYNC REQUEST (ID: [req.id])"
log_data += "\t[uppertext(req.method)] [req.url]"
log_data += "\tRequest body: [req.body]"
log_data += "\tRequest headers: [req.headers]"
log_data += "END ASYNC REQUEST (ID: [req.id])"
// Write the log data
rustg_log_write(GLOB.http_log, log_data.Join("\n[GLOB.log_end]"))
/**
* Blocking request creator
*
* Generates a blocking request, executes it, logs the info then cleanly returns the response
* Exists as a proof of concept, and should never be used
*/
/datum/controller/subsystem/http/proc/make_blocking_request(method, url, body = "", list/headers)
CRASH("Attempted use of a blocking HTTP request")
/*
var/datum/http_request/req = new()
req.prepare(method, url, body, headers)
req.execute_blocking()
var/datum/http_response/res = req.into_response()
// Now generate a logfile
var/list/log_data = list()
log_data += "NEW BLOCKING REQUEST"
log_data += "\t[uppertext(req.method)] [req.url]"
log_data += "\tRequest body: [req.body]"
log_data += "\tRequest headers: [req.headers]"
if(res.errored)
log_data += "\t ----- RESPONSE ERRROR -----"
log_data += "\t [res.error]"
else
log_data += "\tResponse status code: [res.status_code]"
log_data += "\tResponse body: [res.body]"
log_data += "\tResponse headers: [json_encode(res.headers)]"
log_data += "END BLOCKING REQUEST"
// Write the log data
rustg_log_write(GLOB.http_log, log_data.Join("\n[GLOB.log_end]"))
return res
*/
/*
Example of how to use callbacks properly
/client/verb/testing()
set name = "Testing"
var/datum/callback/cb = CALLBACK(src, /client/.proc/response, usr)
SShttp.create_async_request(RUSTG_HTTP_METHOD_GET, "http://site.domain/page.html", proc_callback=cb)
/client/proc/response(mob/user, datum/http_response/response)
to_chat(user, "<span class='notice'>Code: [response.status_code] | Content: [response.body]")
*/