Mongoose should render an html file - c++

I observed that when the Mongoose server event handler is NULL, an HTML file (for example, localhost:8080/index.html) is rendered without any hassles at out.
Here's the code taken from the example of the Mongoose Github repo at https://github.com/cesanta/mongoose.
int main(void) {
struct mg_server *server = mg_create_server(NULL, NULL);
mg_set_option(server, "listening_port", "8080");
printf("Starting on port %s\n", mg_get_option(server, "listening_port"));
for (;;) {
mg_poll_server(server, 1000);
}
mg_destroy_server(&server);
return 0;
}
I want to use the event handler of Mongoose to handle requests. Saw a tutorial here: https://github.com/cesanta/mongoose/blob/master/examples/post.c. The only problem is that I can't access my index.html file unless it is initialized as embedded file as shown in the code below. I want to remove the embedded file version and render the actual html file.
#include <stdio.h>
#include <string.h>
#include "mongoose.h"
static const char *html_form =
"<html><body>"
"<form action=\"/handle_request\">"
"<input type=\"text\" name=\"request_value\" /> <br/>"
"<input type=\"submit\" />"
"</form></body></html>";
static void send_reply(struct mg_connection *conn) {
char value[500];
if(strcmp(conn->uri, "/handle_request") == 0) {
mg_get_var(conn, "request_value", value, sizeof(value));
mg_send_header(conn, "Content-Type", "text/plain");
mg_printf_data( conn, value );
} if(strcmp(conn->uri, "/index.html") == 0) {
// #######################
// HELP ME HERE
// #######################
// Render the html file.
// #######################
} else {
mg_send_data(conn, html_form, strlen(html_form));
}
}
static int ev_handler( struct mg_connection *conn, enum mg_event ev ) {
if ( ev == MG_REQUEST ) {
send_reply( conn );
return MG_TRUE;
} else if ( ev == MG_AUTH ) {
return MG_TRUE;
} else {
return MG_FALSE;
}
}
int main(void) {
struct mg_server *server = mg_create_server(NULL, ev_handler);
mg_set_option(server, "listening_port", "8080");
printf("Starting on port %s\n", mg_get_option(server, "listening_port"));
for (;;) {
mg_poll_server(server, 1000);
}
mg_destroy_server(&server);
return 0;
}
Any suggestions? Thanks in advance.

Set document_root option.
Change // HELP ME HERE to return MG_FALSE;
The rule of thumb is: if event handler returns MG_FALSE, then mongoose does the default action. For MG_REQUEST event the default action is to serve requested file.

Related

How can I start a download from c++ code compiled web assembly?

I've been trying to not do this javascript side and I haven't found anything satisfying yet.
Fetch API seems to be a good lead, but I can't seem to find a way to start the download in the browser so it can download a zip file.
This is emscripten code snippet, but it seems to be a local file of some sort.
#include <stdio.h>
#include <string.h>
#include <emscripten/fetch.h>
void downloadSucceeded(emscripten_fetch_t *fetch) {
printf("Finished downloading %llu bytes from URL %s.\n", fetch->numBytes, fetch->url);
// The data is now available at fetch->data[0] through fetch->data[fetch->numBytes-1];
emscripten_fetch_close(fetch); // Free data associated with the fetch.
}
void downloadFailed(emscripten_fetch_t *fetch) {
printf("Downloading %s failed, HTTP failure status code: %d.\n", fetch->url, fetch->status);
emscripten_fetch_close(fetch); // Also free data on failure.
}
int main() {
emscripten_fetch_attr_t attr;
emscripten_fetch_attr_init(&attr);
strcpy(attr.requestMethod, "GET");
attr.attributes = EMSCRIPTEN_FETCH_LOAD_TO_MEMORY;
attr.onsuccess = downloadSucceeded;
attr.onerror = downloadFailed;
emscripten_fetch(&attr, "myfile.dat");
}
Add this to your cpp file.
EM_JS(void, DownloadUrl, (const char* str),
{
url = UTF8ToString(str);
var hiddenIFrameID = 'hiddenDownloader';
var iframe = document.getElementById(hiddenIFrameID);
if (iframe === null)
{
iframe = document.createElement('iframe');
iframe.id = hiddenIFrameID;
iframe.style.display = 'none';
document.body.appendChild(iframe);
}
iframe.src = url;
});
And an example on how to use it.
void Device::DrawContent()
{
ImGui::Begin("DW Store");
if (ImGui::Button("Download"))
{
DownloadUrl("https://dotnet.microsoft.com/download/dotnet/thank-you/sdk-5.0.402-macos-x64-installer");
}
ImGui::End();
}

How to do IPC using Unix Domain Socket in D?

Here I have a program that wants to
detect whether if it's the only instance
1.1. it does that by trying to create a Unix Domain Socket
and trying to binding it to a specific address.
if a duplicate program is not running, establish an UDS
and then listen to the socket.
2.1. if any message comes through that socket, the program will log the incoming message
2.2. otherwise it should keep listening to the socket forever
if there's a duplicate program it should send a message and then exit.
Here's what I have:
import std.socket, std.experimental.logger;
immutable string socketAddress = "\0/tmp/com.localserver.myapp";
void main()
{
auto socket = new std.socket.Socket(std.socket.AddressFamily.UNIX,
std.socket.SocketType.STREAM);
auto addr = new std.socket.UnixAddress(socketAddress);
auto isUnique = () {
bool result;
scope (success)
log("returns: ", result);
try
{
socket.bind(addr);
result = true;
}
catch (std.socket.SocketOSException e)
result = false;
// else throw error
return result;
}();
if (isUnique)
{
log("Unique instance detected. Listening...");
// works upto now
char[] buffer = [];
while (1)
{
socket.listen(0);
socket.receive(buffer);
if (buffer != []) {
log("Received message: ", buffer);
}
buffer = [];
}
}
else
{
log("Duplicate instance detected.");
socket.connect(addr);
import std.stdio;
stdout.write("Enter your message:\t");
socket.send(readln());
log("Message has been sent. Exiting.");
}
}
The documentation does not seem very friendly to those who does not have any experience in socket programming. How can I send and receive message with std.socket.Socket?
After binding, you actually need to accept. It will return a new Socket instance which you can actually receive from. Your client side branch looks ok. I think that is your key mistake here.
I also have a code sample in my book that shows basic functionality of std.socket which can help as an example:
http://arsdnet.net/dcode/book/chapter_02/03/
it is tcp, but making it unix just means changing the family, like you already did in your code.
You can also look up socket tutorials for C and so on, the D socket is just a thin wrapper around those same BSD style socket functions.
As Adam pointed out I had use listen() method first and then apply the accept() method which returns a socket that can receive message. Then the receiver socket takes a char[N] buffer.
import std.socket, std.experimental.logger;
class UDSIPC
{
private:
static immutable string socketAddress = "\0/tmp/com.localserver.myapp";
static immutable size_t messageBufferSize = 64;
static immutable string socketAddressName = "\0/tmp/com.localserver.myapp";
Socket socket;
UnixAddress uaddr;
public:
this(in string socketAddressName = socketAddressName)
{
socket = new Socket(AddressFamily.UNIX, SocketType.STREAM);
uaddr = new UnixAddress(socketAddress);
}
bool getUniqueness()
{
bool result;
scope (success)
log("returns: ", result);
try
{
socket.bind(uaddr);
result = true;
}
catch (SocketOSException e)
result = false;
// else throw error
return result;
}
string getMessage()
{
socket.listen(0);
auto receiverSocket = socket.accept();
char[messageBufferSize] buffer;
auto amount = receiverSocket.receive(buffer);
import std.string;
return format!"%s"(buffer[0 .. amount]);
}
void sendMessage(in string message)
{
socket.connect(uaddr);
socket.send(message);
}
}
void main()
{
auto ipc = new UDSIPC();
if (ipc.getUniqueness())
{
while (true)
{
log(ipc.getMessage());
}
}
else
{
import std.stdio, std.string;
ipc.sendMessage(readln().chomp());
}
}

Arduinojson pass variables scope

I am having trouble with the code below. I'm coding a ESP8266 wifi module so that it will register automatically to a MQTT server. To make it easy to configure I made a portal that you can access when you first connect the device. Here you can enter the API key and the IOT path name of your device. I want to load and store these configs from a json.config file. This works, expect I can't seem to pass the variables to the void setup scope. The code is stil filled with my last efforts.
Any pointers on how to fix this?
#include <ArduinoJson.h>
#include <ESP8266WebServer.h>
#include "FS.h"
ESP8266WebServer server ( 80 );
char* ssid;
char* password;
char* apikey;
char* iotpath;
void setup() {
const char* values = loadConfig();
Serial.println(values);
// declare ssid and password
//char* ssid = "xxxxxxx";
//char* password = "xxxxxxxx";
// start serial connection and SPIFFS
Serial.begin (115200);
SPIFFS.begin();
Serial.println(ssid);
Serial.println(password);
Serial.println(apikey);
Serial.println(iotpath);
// WiFi connection sequence
WiFi.begin ( ssid, password );
while ( WiFi.status() != WL_CONNECTED ) {
delay ( 500 ); Serial.print ( "." );
}
// WiFi success print
Serial.println ( "" );
Serial.print ( "Connected to " ); Serial.println ( ssid );
Serial.print ( "IP address: " ); Serial.println ( WiFi.localIP() );
// Check if SPIFSS is started
if (!SPIFFS.begin())
{
Serial.println("SPIFFS Mount failed");
} else {
Serial.println("SPIFFS Mount succesfull");
}
// check if config file was loaded
/*
if (!loadConfig()) {
Serial.println("Failed to load config");
} else {
Serial.println("Config loaded");
}*/
// Server root handling
server.serveStatic("/img", SPIFFS, "/img");
server.serveStatic("/", SPIFFS, "/index.html");
server.serveStatic("/css", SPIFFS, "/css");
server.begin();
Serial.println ( "HTTP server started" );
}
void loop() {
// put your main code here, to run repeatedly:
server.handleClient();
delay(100);
//Serial.println(".");
}
const char* loadConfig() {
File configFile = SPIFFS.open("/config.json", "r");
if (!configFile) {
Serial.println("Failed to open config file");
//return false;
}
size_t size = configFile.size();
if (size > 1024) {
Serial.println("Config file size is too large");
//return false;
}
// Allocate a buffer to store contents of the file.
std::unique_ptr<char[]> buf(new char[size]);
// We don't use String here because ArduinoJson library requires the input
// buffer to be mutable. If you don't use ArduinoJson, you may as well
// use configFile.readString instead.
configFile.readBytes(buf.get(), size);
StaticJsonBuffer<200> jsonBuffer;
JsonObject& json = jsonBuffer.parseObject(buf.get());
if (!json.success()) {
Serial.println("Failed to parse config file");
//return false;
}
const char* ssid = json["ssid"];
const char* password= json["password"];
const char* apikey = json["apikey"];
const char* iotpath = json["iotpath"];
//String ssid_string = String(ssid);
//return ssid;
}

Node.JS C++ Native Addon read/write file?

The current problem I am facing with my project is that I do not know how to read/write files from the native node.js addon.
I have to build a type of encryption decryption ( RC6 algorithm ) program. But in order to encrypt files, i should be able to somehow read and write to them from "node-webkit". I am building the .cc file with nw-gyp, and tried multiple possibilities but none worked.
I am building my project with "grunt-node-webkit-builder" and I simply want to read/write one file from the build folder "nw" where nw.exe is located.
The Structure looks like this:
.webkitbuilds
.releases
.nw
.win
.nw
encrypt.txt
ffmpegsumo.dll
icudt.dll
libEGL.dll
libGLESv2.dll
nw.exe
nw.pak
How can I read in my c++ native node.js addon that "encrypt.txt" file.
Help ?
Edit:
Is there any way to use libuv with crypto ++ ?
EDIT 2:
I have the following code. The moment I execute it, the window freezes.
hello.cc:
#include <node.h>
#include <v8.h>
#include <stdio.h>
#include <fcntl.h>
using namespace v8;
#define __S_IREAD 0400 /* Read by owner. */
#define __S_IWRITE 0200 /* Write by owner. */
#define __S_IEXEC 0100 /* Execute by owner. */
#define S_IRUSR __S_IREAD /* Read by owner. */
uv_loop_t* loop;
uv_fs_t open_req;
void open_cb(uv_fs_t* req);
const char* path = "encrypt.txt";
void open_cb(uv_fs_t* req) {
int result = req->result;
if (result == -1) {
fprintf(stderr, "Error at opening file: %s\n",
uv_strerror(uv_last_error(loop)));
}
uv_fs_req_cleanup(req);
printf("Successfully opened file.\n");
}
char *get(v8::Local<v8::Value> value, const char *fallback = "") {
if (value->IsString()) {
v8::String::AsciiValue string(value);
char *str = (char *) malloc(string.length() + 1);
strcpy(str, *string);
return str;
}
char *str = (char *) malloc(strlen(fallback) + 1);
strcpy(str, fallback);
return str;
}
Handle<Value> Encrypt(const Arguments& args) {
HandleScope scope;
char* textToEncrypt = get(args[0], "str");
char* password = get(args[1], "str");
loop = uv_default_loop();
int r = uv_fs_open(loop, &open_req, path, O_RDONLY, S_IRUSR, open_cb);
if (r) {
fprintf(stderr, "Error at opening file: %s\n",
uv_strerror(uv_last_error(loop)));
}
uv_run(loop, UV_RUN_DEFAULT);
return scope.Close(String::New("done"));
}
void Init(Handle<Object> exports) {
exports->Set(String::NewSymbol("Encrypt"),
FunctionTemplate::New(Encrypt)->GetFunction());
}
NODE_MODULE(hello, Init)
In Javascript :
var application = require('./js/build/Release/hello');
var encrypted_data = "";
$(document).ready(function() {
$('#btn_encrypt').on('click', function() {
encrypted_data = application.Encrypt("val","val");
console.log(encrypted_data);
})
});

mongoose web server helloworld program

I came across an embedded web server named mongoose and http://code.google.com/p/mongoose/ and I read the wiki it was great and i searched for some sample hello world program but i couldn't find it... i found some example but that was written in c++ for windows and can any one provide an example c program to run this webserver..
It is quite simple, first you need to implement the call back function:
void *event_handler(enum mg_event event,
struct mg_connection *conn) {
const struct mg_request_info *request_info = mg_get_request_info(conn);
static void* done = "done";
if (event == MG_NEW_REQUEST) {
if (strcmp(request_info->uri, "/hello") == 0) {
// handle c[renderer] request
if(strcmp(request_info->request_method, "GET") != 0) {
// send error (we only care about HTTP GET)
mg_printf(conn, "HTTP/1.1 %d Error (%s)\r\n\r\n%s",
500,
"we only care about HTTP GET",
"we only care about HTTP GET");
// return not null means we handled the request
return done;
}
// handle your GET request to /hello
char* content = "Hello World!";
char* mimeType = "text/plain";
int contentLength = strlen(content);
mg_printf(conn,
"HTTP/1.1 200 OK\r\n"
"Cache: no-cache\r\n"
"Content-Type: %s\r\n"
"Content-Length: %d\r\n"
"\r\n",
mimeType,
contentLength);
mg_write(conn, content, contentLength);
return done;
}
}
// in this example i only handle /hello
mg_printf(conn, "HTTP/1.1 %d Error (%s)\r\n\r\n%s",
500, /* This the error code you want to send back*/
"Invalid Request.",
"Invalid Request.");
return done;
}
// No suitable handler found, mark as not processed. Mongoose will
// try to serve the request.
return NULL;
}
Then you need to start the server:
int main(int argc, char **argv) {
/* Default options for the HTTP server */
const char *options[] = {
"listening_ports", "8081",
"num_threads", "10",
NULL
};
/* Initialize HTTP layer */
static struct mg_context *ctx;
ctx = mg_start(&event_handler, options);
if(ctx == NULL) {
exit(EXIT_FAILURE);
}
puts("Server running, press enter to exit\n");
getchar();
mg_stop(ctx);
return EXIT_SUCCESS;
}
I wrote a C++ REST service library that uses Mongoose. Here's a simple example:
#include <iostream>
#include <server/server.hpp>
int main()
{
using namespace pwned::server;
Server server;
server.Get("/", [](mg_event*, Params const &) {
return Server::response("Hello!");
});
std::cin.get();
}
Based on
https://github.com/nurettin/pwned/blob/master/examples/server/basics/server.cpp
Compile application: $ cc my_app.c mongoose.c
#include "mongoose.h" // Include Mongoose API definitions
static const char *s_http_port = "8089";
// Define an event handler function
static void ev_handler(struct mg_connection *nc, int ev, void *ev_data)
{
struct mbuf *io = &nc->recv_mbuf;
switch (ev)
{
case MG_EV_RECV:
// This event handler implements simple TCP echo server
mg_send(nc, io->buf, io->len); // Echo received data back
mbuf_remove(io, io->len); // Discard data from recv buffer
break;
default:
break;
}
}
int main(void)
{
struct mg_mgr mgr;
mg_mgr_init(&mgr, NULL); // Initialize event manager object
// Note that many connections can be added to a single event manager
// Connections can be created at any point, e.g. in event handler function
mg_bind(&mgr, s_http_port, ev_handler); // Create listening connection and add it to the event manager
for (;;)
{
// Start infinite event loop
mg_mgr_poll(&mgr, 1000);
}
mg_mgr_free(&mgr);
return 0;
}
For anyone looking at this thread - from the mongoose library author (me).
Mongoose web server has long ago moved to https://github.com/cesanta/mongoose
It has a comprehensive list of examples, starting from a simplest ones, to the more complex ones, see examples directory in the repository. The minimal static HTTP server goes as follows:
#include "mongoose.h"
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
struct mg_http_serve_opts opts = {.root_dir = "."}; // Serve local dir
if (ev == MG_EV_HTTP_MSG) mg_http_serve_dir(c, ev_data, &opts);
}
int main(int argc, char *argv[]) {
struct mg_mgr mgr;
mg_mgr_init(&mgr); // Init manager
mg_http_listen(&mgr, "http://localhost:8000", fn, &mgr); // Setup listener
for (;;) mg_mgr_poll(&mgr, 1000); // Event loop
mg_mgr_free(&mgr); // Cleanup
return 0;
}