Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
M
mongoose
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
esp
mongoose
Commits
d0e27418
Commit
d0e27418
authored
Jan 04, 2014
by
Sergey Lyubka
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added new response creation interface
parent
3a5e2fba
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
129 additions
and
50 deletions
+129
-50
page.mg.lua
build/test/page.mg.lua
+0
-0
API.md
docs/API.md
+28
-10
hello.c
examples/hello.c
+3
-3
mongoose.c
mongoose.c
+89
-36
mongoose.h
mongoose.h
+9
-1
No files found.
build/test/page.
lp
→
build/test/page.
mg.lua
View file @
d0e27418
File moved
docs/API.md
View file @
d0e27418
...
...
@@ -112,16 +112,34 @@ is returned.
This is an interface primarily designed to push arbitrary data to websocket
connections at any time. This function could be called from any thread. When
it returns, an IO thread called
`func()`
on each active websocket connection,
passing
`param`
as an extra parameter. It is allowed to call
`mg_write()`
or
`mg_websocket_write()`
within a callback, cause these write functions are
thread-safe.
int mg_write(struct mg_connection *, const void *buf, int len);
Send data to the client. This function is thread-safe. This function appends
given buffer to a send queue of a given connection. It may return 0 if
there is not enough memory, in which case the data will not be sent.
it returns, an IO thread called
`func()`
on each active connection,
passing
`param`
as an extra parameter. It is allowed to call
`mg_send_data()`
or
`mg_websocket_write()`
within a callback, cause
`func`
is executed in the
context of the IO thread.
void mg_send_status(struct mg_connection *, int status_code);
void mg_send_header(struct mg_connection *, const char *name,
const char *value);
void mg_send_data(struct mg_connection *, const void *data, int data_len);
void mg_printf_data(struct mg_connection *, const char *format, ...);
These functions are used to construct a response to the client. HTTP response
consists of three parts:
*
a status line
*
zero or more HTTP headers
*
response body
Mongoose provides functions for all three parts:
*
`mg_send_status()`
is used to create status line. This function can be
called zero or once. If
`mg_send_status()`
is not called, then Mongoose
will send status 200 (success) implicitly.
*
`mg_send_header()`
adds HTTP header to the response. This function could
be called zero or more times.
*
`mg_send_data()`
and
`mg_printf_data()`
are used to send data to the
client. Note that Mongoose adds
`Transfer-Encoding: chunked`
header
implicitly, and sends data in chunks. Therefore, it is not necessary to
set
`Content-Length`
header.
int mg_websocket_write(struct mg_connection* conn, int opcode,
const char *data, size_t data_len);
...
...
examples/hello.c
View file @
d0e27418
...
...
@@ -4,9 +4,9 @@
// This function will be called by mongoose on every new request
static
int
index_html
(
struct
mg_connection
*
conn
)
{
mg_printf
(
conn
,
"HTTP/1.0 200 OK
\r\n\r\n
"
"Hello! Requested URI is [%s], query string is [%s]"
,
conn
->
uri
,
conn
->
query_string
==
NULL
?
"(none)"
:
conn
->
query_string
);
mg_printf
_data
(
conn
,
"Hello! Requested URI is [%s], query string is [%s]"
,
conn
->
uri
,
conn
->
query_string
==
NULL
?
"(none)"
:
conn
->
query_string
);
return
0
;
}
...
...
mongoose.c
View file @
d0e27418
...
...
@@ -227,7 +227,8 @@ union endpoint {
enum
endpoint_type
{
EP_NONE
,
EP_FILE
,
EP_CGI
,
EP_USER
,
EP_PUT
};
enum
connection_flags
{
CONN_CLOSE
=
1
,
CONN_SPOOL_DONE
=
2
,
CONN_SSL_HANDS_SHAKEN
=
4
CONN_CLOSE
=
1
,
CONN_SPOOL_DONE
=
2
,
CONN_SSL_HANDS_SHAKEN
=
4
,
CONN_HEADERS_SENT
=
8
};
struct
connection
{
...
...
@@ -445,28 +446,32 @@ static int mg_snprintf(char *buf, size_t buflen, const char *fmt, ...) {
return
n
;
}
static
const
char
*
status_code_to_str
(
int
status_code
)
{
switch
(
status_code
)
{
case
200
:
return
"OK"
;
case
201
:
return
"Created"
;
case
204
:
return
"No Content"
;
case
304
:
return
"Not Modified"
;
case
400
:
return
"Bad Request"
;
case
403
:
return
"Forbidden"
;
case
404
:
return
"Not Found"
;
case
405
:
return
"Method Not Allowed"
;
case
409
:
return
"Conflict"
;
case
411
:
return
"Length Required"
;
case
413
:
return
"Request Entity Too Large"
;
case
415
:
return
"Unsupported Media Type"
;
case
423
:
return
"Locked"
;
case
500
:
return
"Server Error"
;
case
501
:
return
"Not Implemented"
;
default:
return
"Server Error"
;
}
}
static
void
send_http_error
(
struct
connection
*
conn
,
int
code
)
{
const
char
*
message
;
const
char
*
message
=
status_code_to_str
(
code
)
;
char
headers
[
200
],
body
[
200
];
int
body_len
,
headers_len
;
switch
(
code
)
{
case
201
:
message
=
"Created"
;
break
;
case
204
:
message
=
"No Content"
;
break
;
case
304
:
message
=
"Not Modified"
;
break
;
case
400
:
message
=
"Bad Request"
;
break
;
case
403
:
message
=
"Forbidden"
;
break
;
case
404
:
message
=
"Not Found"
;
break
;
case
405
:
message
=
"Method Not Allowed"
;
break
;
case
409
:
message
=
"Conflict"
;
break
;
case
411
:
message
=
"Length Required"
;
break
;
case
413
:
message
=
"Request Entity Too Large"
;
break
;
case
415
:
message
=
"Unsupported Media Type"
;
break
;
case
423
:
message
=
"Locked"
;
break
;
case
501
:
message
=
"Not Implemented"
;
break
;
default:
message
=
"Server Error"
;
break
;
}
conn
->
mg_conn
.
status_code
=
code
;
body_len
=
mg_snprintf
(
body
,
sizeof
(
body
),
"%d %s
\n
"
,
code
,
message
);
if
(
code
>=
300
&&
code
<=
399
)
{
...
...
@@ -522,12 +527,25 @@ static int alloc_vprintf(char **buf, size_t size, const char *fmt, va_list ap) {
return
len
;
}
int
mg_vprintf
(
struct
mg_connection
*
conn
,
const
char
*
fmt
,
va_list
ap
)
{
static
void
write_chunk
(
struct
connection
*
conn
,
const
char
*
buf
,
int
len
)
{
char
chunk_size
[
50
];
int
n
=
mg_snprintf
(
chunk_size
,
sizeof
(
chunk_size
),
"%X
\r\n
"
,
len
);
spool
(
&
conn
->
remote_iobuf
,
chunk_size
,
n
);
spool
(
&
conn
->
remote_iobuf
,
buf
,
len
);
spool
(
&
conn
->
remote_iobuf
,
"
\r\n
"
,
2
);
}
int
mg_vprintf
(
struct
mg_connection
*
conn
,
const
char
*
fmt
,
va_list
ap
,
int
chunked
)
{
char
mem
[
IOBUF_SIZE
],
*
buf
=
mem
;
int
len
;
if
((
len
=
alloc_vprintf
(
&
buf
,
sizeof
(
mem
),
fmt
,
ap
))
>
0
)
{
len
=
mg_write
(
conn
,
buf
,
(
size_t
)
len
);
if
(
chunked
)
{
write_chunk
((
struct
connection
*
)
conn
,
buf
,
len
);
}
else
{
len
=
mg_write
(
conn
,
buf
,
(
size_t
)
len
);
}
}
if
(
buf
!=
mem
&&
buf
!=
NULL
)
{
free
(
buf
);
...
...
@@ -537,9 +555,12 @@ int mg_vprintf(struct mg_connection *conn, const char *fmt, va_list ap) {
}
int
mg_printf
(
struct
mg_connection
*
conn
,
const
char
*
fmt
,
...)
{
int
len
;
va_list
ap
;
va_start
(
ap
,
fmt
);
return
mg_vprintf
(
conn
,
fmt
,
ap
);
len
=
mg_vprintf
(
conn
,
fmt
,
ap
,
0
);
va_end
(
ap
);
return
len
;
}
// A helper function for traversing a comma separated list of values.
...
...
@@ -1292,6 +1313,45 @@ int mg_write(struct mg_connection *c, const void *buf, int len) {
return
spool
(
&
((
struct
connection
*
)
c
)
->
remote_iobuf
,
buf
,
len
);
}
void
mg_send_status
(
struct
mg_connection
*
c
,
int
status
)
{
if
(
c
->
status_code
==
0
)
{
c
->
status_code
=
status
;
mg_printf
(
c
,
"HTTP/1.1 %d %s
\r\n
"
,
status
,
status_code_to_str
(
status
));
}
}
void
mg_send_header
(
struct
mg_connection
*
c
,
const
char
*
name
,
const
char
*
v
)
{
if
(
c
->
status_code
==
0
)
{
c
->
status_code
=
200
;
mg_printf
(
c
,
"HTTP/1.1 %d %s
\r\n
"
,
200
,
status_code_to_str
(
200
));
}
mg_printf
(
c
,
"%s: %s
\r\n
"
,
name
,
v
);
}
static
void
terminate_headers
(
struct
mg_connection
*
c
)
{
struct
connection
*
conn
=
(
struct
connection
*
)
c
;
if
(
!
(
conn
->
flags
&
CONN_HEADERS_SENT
))
{
mg_send_header
(
c
,
"Transfer-Encoding"
,
"chunked"
);
mg_write
(
c
,
"
\r\n
"
,
2
);
conn
->
flags
|=
CONN_HEADERS_SENT
;
}
}
void
mg_send_data
(
struct
mg_connection
*
c
,
const
void
*
data
,
int
data_len
)
{
terminate_headers
(
c
);
write_chunk
((
struct
connection
*
)
c
,
data
,
data_len
);
}
void
mg_printf_data
(
struct
mg_connection
*
c
,
const
char
*
fmt
,
...)
{
va_list
ap
;
terminate_headers
(
c
);
va_start
(
ap
,
fmt
);
mg_vprintf
(
c
,
fmt
,
ap
,
1
);
va_end
(
ap
);
}
#if !defined(NO_WEBSOCKET) || !defined(NO_AUTH)
static
int
is_big_endian
(
void
)
{
static
const
int
n
=
1
;
...
...
@@ -1852,6 +1912,9 @@ static void call_uri_handler_if_data_is_buffered(struct connection *conn) {
#endif
if
(
loc
->
len
>=
c
->
content_len
)
{
conn
->
endpoint
.
uh
->
handler
(
c
);
if
(
conn
->
flags
&
CONN_HEADERS_SENT
)
{
write_chunk
(
conn
,
""
,
0
);
// Write final zero-length chunk
}
close_local_endpoint
(
conn
);
}
}
...
...
@@ -2032,16 +2095,6 @@ static void mg_url_encode(const char *src, char *dst, size_t dst_len) {
#endif // !NO_DIRECTORY_LISTING || !NO_DAV
#ifndef NO_DIRECTORY_LISTING
static
int
mg_write_chunked
(
struct
connection
*
conn
,
const
char
*
buf
,
int
len
)
{
char
chunk_size
[
50
];
int
n
=
mg_snprintf
(
chunk_size
,
sizeof
(
chunk_size
),
"%X
\r\n
"
,
len
);
n
=
spool
(
&
conn
->
remote_iobuf
,
chunk_size
,
n
);
n
+=
spool
(
&
conn
->
remote_iobuf
,
buf
,
len
);
n
+=
spool
(
&
conn
->
remote_iobuf
,
"
\r\n
"
,
2
);
return
n
;
}
static
void
print_dir_entry
(
const
struct
dir_entry
*
de
)
{
char
size
[
64
],
mod
[
64
],
href
[
MAX_PATH_SIZE
*
3
],
chunk
[
MAX_PATH_SIZE
*
4
];
...
...
@@ -2071,7 +2124,7 @@ static void print_dir_entry(const struct dir_entry *de) {
"<td> %s</td><td> %s</td></tr>
\n
"
,
de
->
conn
->
mg_conn
.
uri
,
href
,
slash
,
de
->
file_name
,
slash
,
mod
,
size
);
mg_write_chunked
((
struct
connection
*
)
de
->
conn
,
chunk
,
n
);
write_chunk
((
struct
connection
*
)
de
->
conn
,
chunk
,
n
);
}
// Sort directory entries by size, or name, or modification time.
...
...
@@ -2124,7 +2177,7 @@ static void send_directory_listing(struct connection *conn, const char *dir) {
"<tr><td colspan=
\"
3
\"
><hr></td></tr>"
,
conn
->
mg_conn
.
uri
,
conn
->
mg_conn
.
uri
,
sort_direction
,
sort_direction
,
sort_direction
);
mg_write_chunked
(
conn
,
buf
,
strlen
(
buf
));
write_chunk
(
conn
,
buf
,
strlen
(
buf
));
num_entries
=
scan_directory
(
conn
,
dir
,
&
arr
);
qsort
(
arr
,
num_entries
,
sizeof
(
arr
[
0
]),
compare_dir_entries
);
...
...
@@ -2134,7 +2187,7 @@ static void send_directory_listing(struct connection *conn, const char *dir) {
}
free
(
arr
);
mg_write_chunked
(
conn
,
""
,
0
);
// Write final zero-length chunk
write_chunk
(
conn
,
""
,
0
);
// Write final zero-length chunk
close_local_endpoint
(
conn
);
}
#endif // NO_DIRECTORY_LISTING
...
...
@@ -3226,7 +3279,7 @@ static void log_access(const struct connection *conn, const char *path) {
static
void
close_local_endpoint
(
struct
connection
*
conn
)
{
// Must be done before free()
int
keep_alive
=
should_keep_alive
(
&
conn
->
mg_conn
)
&&
conn
->
endpoint_type
==
EP_FILE
;
(
conn
->
endpoint_type
==
EP_FILE
||
conn
->
endpoint_type
==
EP_USER
)
;
switch
(
conn
->
endpoint_type
)
{
case
EP_FILE
:
close
(
conn
->
endpoint
.
fd
);
break
;
...
...
mongoose.h
View file @
d0e27418
...
...
@@ -74,11 +74,19 @@ void mg_iterate_over_connections(struct mg_server *,
void
*
param
);
// Connection management functions
int
mg_write
(
struct
mg_connection
*
,
const
void
*
buf
,
int
len
);
void
mg_send_status
(
struct
mg_connection
*
,
int
status_code
);
void
mg_send_header
(
struct
mg_connection
*
,
const
char
*
name
,
const
char
*
val
);
void
mg_send_data
(
struct
mg_connection
*
,
const
void
*
data
,
int
data_len
);
void
mg_printf_data
(
struct
mg_connection
*
,
const
char
*
format
,
...);
int
mg_websocket_write
(
struct
mg_connection
*
,
int
opcode
,
const
char
*
data
,
size_t
data_len
);
// Deprecated in favor of mg_send_* interface
int
mg_write
(
struct
mg_connection
*
,
const
void
*
buf
,
int
len
);
int
mg_printf
(
struct
mg_connection
*
conn
,
const
char
*
fmt
,
...);
const
char
*
mg_get_header
(
const
struct
mg_connection
*
,
const
char
*
name
);
const
char
*
mg_get_mime_type
(
const
char
*
file_name
);
int
mg_get_var
(
const
struct
mg_connection
*
conn
,
const
char
*
var_name
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment