Skip to content

Serving Files

Eugene edited this page Mar 18, 2019 · 6 revisions

Additions to the Onion-based Program

  1. Add the base URL, e.g., http://localhost:2048/assets, that will be responsible for serving out the files. Use a regular expression, e.g., ^assets, that will match the base URL and pass on the remaining URL to the handler:
onion *o = onion_new(O_THREADED);
onion_set_hostname(o, "localhost");
onion_set_port(o, "2048");
onion_url *urls = onion_root_url(o);
onion_url_add(urls, "", handler_root);
onion_url_add(urls, "^assets", handler_assets);
  1. Define the handler function, similar to onion_handler_export_local_new(...) in handlers/exportlocal.c
static onion_connection_status handler_assets(void *_, onion_request *req,
                                              onion_response *res) {
	build_response_header(res);
	const char local_path[] = "../src/assets/";
	char *global_path = realpath(local_path, NULL);
	if (!global_path) {
		ONION_ERROR("Cannot calculate the global path of the given directory (%s).",
		            local_path);
		return OCS_NOT_IMPLEMENTED;
	}
	struct stat st;
	if (stat(global_path, &st) != 0) {
		ONION_ERROR("Cannot access to the exported directory/file (%s).", global_path);
		onion_low_free(global_path);
		return OCS_NOT_IMPLEMENTED;
	}
	
	const char *filename = onion_request_get_path(req);
	GString *full_filename = g_string_new(global_path);
	g_string_append(full_filename, filename);

	onion_connection_status status = 
	    onion_shortcut_response_file(full_filename->str, req, res);
	g_string_free(full_filename, TRUE);
	return status;
}

The retrieval of the asset (from an absolute file path) is performed by onion_shortcut_response_file(...) in shortcuts.c, which also sets the file's mime type in Onion's response header.

Mime Types Under macOS

Note: All the changes detailed here have already been applied to this fork of the Onion library.

For Onion to apply the correct mime type to files it serves, it reads the /etc/mime.types file that is available on Linux operating systems, but not on macOS. A workaround is to have a local copy of mime.types which can be read when /etc/mime.types cannot be found.

  1. Save a copy of /etc/mime.types to src/onion/mime.types,

  2. Extend onion_mime_fill(...) in mime.c to read the local copy of mime.types.

  3. Optionally extend the default subset of mime types in onion_mime_fill(...) if the local file cannot be read as well.

onion_dict_add(onion_mime_dict, "svg", "image/svg+xml", 0);
onion_dict_add(onion_mime_dict, "pdf", "application/pdf", 0);
Clone this wiki locally