rewrote to use C++ instead of Java
This commit is contained in:
110
src/main.cpp
Normal file
110
src/main.cpp
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
#include "crow.h"
|
||||||
|
#include <pqxx/pqxx>
|
||||||
|
#include <string>
|
||||||
|
#include <fmt/core.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
crow::SimpleApp app;
|
||||||
|
//define your endpoint at the root directory
|
||||||
|
CROW_ROUTE(app, "/")([](){
|
||||||
|
return "Hello world";
|
||||||
|
});
|
||||||
|
|
||||||
|
// CROW_ROUTE(app, "/test.json")
|
||||||
|
// ([](){
|
||||||
|
// pqxx::connection db("postgresql://cavecommadmin:cavecomm@localhost:5432/cavecomm");
|
||||||
|
// pqxx::work work(db);
|
||||||
|
// pqxx::result result = work.exec("SELECT * from public.requests;");
|
||||||
|
// work.commit();
|
||||||
|
// return crow::json::wvalue x({{"message", rows[0][0].as<int>();}});
|
||||||
|
// });
|
||||||
|
|
||||||
|
CROW_ROUTE(app, "/test")
|
||||||
|
([](){
|
||||||
|
pqxx::connection db("postgresql://cavecommadmin:cavecomm@localhost:5432/cavecomm");
|
||||||
|
pqxx::work work(db);
|
||||||
|
pqxx::result result = work.exec("SELECT * from requests;");
|
||||||
|
work.commit();
|
||||||
|
|
||||||
|
return result[0][0].as<string>();
|
||||||
|
});
|
||||||
|
|
||||||
|
CROW_ROUTE(app, "/testRequest")
|
||||||
|
([](){
|
||||||
|
|
||||||
|
string customerEmailAddress = "test@testmail.com";
|
||||||
|
string freelancer = "michael";
|
||||||
|
string templateName = "coding";
|
||||||
|
string currencyPreference = "XMR";
|
||||||
|
string priceUpFront = "0.36";
|
||||||
|
string priceOnDeliver = "0.36";
|
||||||
|
string requestDescription = "This is a test";
|
||||||
|
string accepted = "0";
|
||||||
|
string upFrontInvoiceID = "12424242424";
|
||||||
|
string onDeliverInvoiceID = "329532532532";
|
||||||
|
string upFrontPaid = "0";
|
||||||
|
string onDeliverPaid = "0";
|
||||||
|
string sql = fmt::format("INSERT INTO requests(id, customerEmailAddress, freelancer, templateName, currencyPreference, priceUpFront, priceOnDeliver, requestDescription, accepted, upFrontInvoiceID, onDeliverInvoiceID, upFrontPaid, onDeliverPaid) \
|
||||||
|
VALUES(DEFAULT, '{0}', '{1}', '{2}', '{3}', '{4}', '{5}', '{6}', '{7}', '{8}', '{9}', '{10}', '{11}' );", customerEmailAddress, freelancer, templateName, currencyPreference, priceUpFront, priceOnDeliver, requestDescription, accepted, upFrontInvoiceID, onDeliverInvoiceID, upFrontPaid, onDeliverPaid );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
pqxx::connection db("postgresql://cavecommadmin:cavecomm@localhost:5432/cavecomm");
|
||||||
|
pqxx::work work(db);
|
||||||
|
work.exec( sql );
|
||||||
|
work.commit();
|
||||||
|
|
||||||
|
return crow::response(200);
|
||||||
|
});
|
||||||
|
|
||||||
|
CROW_ROUTE(app, "/newRequest")
|
||||||
|
.methods("POST"_method)
|
||||||
|
([](const crow::request& req){
|
||||||
|
auto jsonBody = crow::json::load(req.body);
|
||||||
|
if (!jsonBody)
|
||||||
|
return crow::response(crow::status::BAD_REQUEST);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Example CURL to insert into DB:
|
||||||
|
* curl -d '{"customerEmailAddress":"test@testmail.com","freelancer":"michael","templateName":"coding","currencyPreference":"XMR","priceUpFront":0.36,"priceOnDeliver":0.36,"requestDescription":"This is a test","accepted":false,"upFrontInvoiceID":"12424242424","onDeliverInvoiceID":"329532532532","upFrontPaid":false,"onDeliverPaid":false}' http://0.0.0.0:18080/newRequest
|
||||||
|
*/
|
||||||
|
|
||||||
|
string customerEmailAddress = jsonBody["customerEmailAddress"].s();
|
||||||
|
string freelancer = jsonBody["freelancer"].s();
|
||||||
|
string templateName = jsonBody["templateName"].s();
|
||||||
|
string currencyPreference = jsonBody["currencyPreference"].s();
|
||||||
|
double priceUpFront = jsonBody["priceUpFront"].d();
|
||||||
|
double priceOnDeliver = jsonBody["priceOnDeliver"].d();
|
||||||
|
string requestDescription = jsonBody["requestDescription"].s();
|
||||||
|
bool accepted = jsonBody["accepted"].b();
|
||||||
|
string upFrontInvoiceID = jsonBody["upFrontInvoiceID"].s();
|
||||||
|
string onDeliverInvoiceID = jsonBody["onDeliverInvoiceID"].s();
|
||||||
|
bool upFrontPaid = jsonBody["upFrontPaid"].b();
|
||||||
|
bool onDeliverPaid = jsonBody["onDeliverPaid"].b();
|
||||||
|
|
||||||
|
string sql = fmt::format("INSERT INTO requests(id, customerEmailAddress, freelancer, templateName, currencyPreference, priceUpFront, priceOnDeliver, requestDescription, accepted, upFrontInvoiceID, onDeliverInvoiceID, upFrontPaid, onDeliverPaid) \
|
||||||
|
VALUES(DEFAULT, '{0}', '{1}', '{2}', '{3}', '{4}', '{5}', '{6}', '{7}', '{8}', '{9}', '{10}', '{11}');", customerEmailAddress, freelancer, templateName, currencyPreference, priceUpFront, priceOnDeliver, requestDescription, accepted ,upFrontInvoiceID , onDeliverInvoiceID, upFrontPaid, onDeliverPaid );
|
||||||
|
|
||||||
|
/*
|
||||||
|
In C++20 this would be valid:
|
||||||
|
sql = std::format("INSERT INTO requests \
|
||||||
|
VALUES(DEFAULT, \"{}\", \"{}\", \"{}\", \"{}\", \"{}\", \"{}\" ,\"{}\" ,\"{}\" ,\"{}\" ,\"{}\", \"{}\", \"{}\");",
|
||||||
|
customerEmailAddress, freelancer, templateName, currencyPreference, priceUpFront, priceOnDeliver, requestDescription, accepted, upFrontInvoiceID, onDeliverInvoiceID, upFrontPaid, onDeliverPaid);
|
||||||
|
*/
|
||||||
|
|
||||||
|
pqxx::connection db("postgresql://cavecommadmin:cavecomm@localhost:5432/cavecomm");
|
||||||
|
pqxx::work work(db);
|
||||||
|
work.exec( sql );
|
||||||
|
work.commit();
|
||||||
|
|
||||||
|
return crow::response(200);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
//set the port, set the app to run on multiple threads, and run the app
|
||||||
|
app.port(18080).multithreaded().run();
|
||||||
|
}
|
@ -1,83 +0,0 @@
|
|||||||
package cavecomm;
|
|
||||||
|
|
||||||
import io.vertx.core.Vertx;
|
|
||||||
import io.vertx.ext.web.RoutingContext;
|
|
||||||
import io.vertx.pgclient.PgConnectOptions;
|
|
||||||
import io.vertx.pgclient.PgPool;
|
|
||||||
import io.vertx.sqlclient.PoolOptions;
|
|
||||||
import io.vertx.sqlclient.Row;
|
|
||||||
import io.vertx.sqlclient.RowSet;
|
|
||||||
import io.vertx.sqlclient.SqlClient;
|
|
||||||
|
|
||||||
public class Database {
|
|
||||||
public static final int OUTPUT_DATATYPE_JSON = 0;
|
|
||||||
public static final int OUTPUT_DATATYPE_HTML = 1;
|
|
||||||
public static final int OUTPUT_DATATYPE_NONE = 2;
|
|
||||||
|
|
||||||
private final PgConnectOptions connectOptions;
|
|
||||||
private final PoolOptions poolOptions;
|
|
||||||
private final Vertx vertx;
|
|
||||||
|
|
||||||
private SqlClient client;
|
|
||||||
|
|
||||||
public Database(Vertx vertx, int port, String host, String database, String user, String password) {
|
|
||||||
this.vertx = vertx;
|
|
||||||
//Sets up the database Connection
|
|
||||||
connectOptions = new PgConnectOptions()
|
|
||||||
.setPort(port)
|
|
||||||
.setHost(host)
|
|
||||||
.setDatabase(database)
|
|
||||||
.setUser(user)
|
|
||||||
.setPassword(password);
|
|
||||||
poolOptions = new PoolOptions();
|
|
||||||
}
|
|
||||||
|
|
||||||
//Executes an SQL query
|
|
||||||
//requires further consideration of the Handling.
|
|
||||||
public void executeQuery(String query)
|
|
||||||
{
|
|
||||||
createClient();
|
|
||||||
client
|
|
||||||
.query(query)
|
|
||||||
.execute(ar -> {
|
|
||||||
if (ar.succeeded()) {
|
|
||||||
RowSet<Row> result = ar.result();
|
|
||||||
//test output
|
|
||||||
for (Row r : result) {
|
|
||||||
|
|
||||||
System.out.println("row: " + r.getString("testcolumn1"));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
System.out.println("Failure: " + ar.cause().getMessage());
|
|
||||||
}
|
|
||||||
closeClient();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
//Executes an SQL query while delivering a context to handle the data
|
|
||||||
//context output is a JSON
|
|
||||||
public void executeQuery(String query, RoutingContext rc, int outputDataType)
|
|
||||||
{
|
|
||||||
createClient();
|
|
||||||
client
|
|
||||||
.query(query)
|
|
||||||
.execute(ar -> {
|
|
||||||
switch (outputDataType) {
|
|
||||||
case OUTPUT_DATATYPE_JSON -> HandlerCollection.outputJSON(ar, rc);
|
|
||||||
case OUTPUT_DATATYPE_HTML -> HandlerCollection.outputHTML(ar, rc);
|
|
||||||
}
|
|
||||||
|
|
||||||
closeClient();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
private void createClient()
|
|
||||||
{
|
|
||||||
client = PgPool.client(vertx, connectOptions, poolOptions);
|
|
||||||
}
|
|
||||||
private void closeClient()
|
|
||||||
{
|
|
||||||
System.out.println("Client Closing");
|
|
||||||
client.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,47 +0,0 @@
|
|||||||
package cavecomm;
|
|
||||||
|
|
||||||
import io.vertx.core.AsyncResult;
|
|
||||||
import io.vertx.core.json.JsonArray;
|
|
||||||
import io.vertx.ext.web.RoutingContext;
|
|
||||||
import io.vertx.sqlclient.Row;
|
|
||||||
import io.vertx.sqlclient.RowSet;
|
|
||||||
|
|
||||||
//Class collecting Handlers to be used instead of Complex Lmabdas
|
|
||||||
public final class HandlerCollection {
|
|
||||||
private HandlerCollection() {
|
|
||||||
}
|
|
||||||
|
|
||||||
//returns a response containing the query result as a JSON
|
|
||||||
public static void outputJSON(AsyncResult<RowSet<Row>> ar, RoutingContext rc) {
|
|
||||||
if (ar.succeeded()) {
|
|
||||||
RowSet<Row> result = ar.result();
|
|
||||||
//dump RowSet into jsonArray
|
|
||||||
JsonArray jsonArray = new JsonArray();
|
|
||||||
for (Row r : result) {
|
|
||||||
jsonArray.add(r.toJson());
|
|
||||||
}
|
|
||||||
//sets the header to json
|
|
||||||
rc.response().putHeader("Content-Type", "application/json; charset=UTF8")
|
|
||||||
.end(jsonArray.encode());
|
|
||||||
} else {
|
|
||||||
System.out.println("Failure: " + ar.cause().getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Potentially unnecessary to exist as its own handler
|
|
||||||
public static void outputHTML(AsyncResult<RowSet<Row>> ar, RoutingContext rc) {
|
|
||||||
if (ar.succeeded()) {
|
|
||||||
RowSet<Row> result = ar.result();
|
|
||||||
//dump RowSet into jsonArray
|
|
||||||
JsonArray jsonArray = new JsonArray();
|
|
||||||
for (Row r : result) {
|
|
||||||
jsonArray.add(r.toJson());
|
|
||||||
}
|
|
||||||
//sets the header to html
|
|
||||||
rc.response().putHeader("Content-Type", "text/html; charset=UTF8")
|
|
||||||
.end(jsonArray.encodePrettily());
|
|
||||||
} else {
|
|
||||||
System.out.println("Failure: " + ar.cause().getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,77 +0,0 @@
|
|||||||
package cavecomm;
|
|
||||||
|
|
||||||
import io.vertx.core.AbstractVerticle;
|
|
||||||
import io.vertx.core.MultiMap;
|
|
||||||
import io.vertx.core.json.JsonObject;
|
|
||||||
import io.vertx.ext.web.Router;
|
|
||||||
|
|
||||||
public class MainVerticle extends AbstractVerticle {
|
|
||||||
@Override
|
|
||||||
public void start() throws Exception {
|
|
||||||
|
|
||||||
//Template Engine / HTML Assembler
|
|
||||||
//
|
|
||||||
//TODO: actually make this work, for some reason io.vertx.ext.web.handler.TemplateEngine doesn't exist even though it does: https://vertx.io/docs/apidocs/io/vertx/ext/web/handler/package-summary.html
|
|
||||||
io.vertx.ext.web.handler.TemplateEngine engine = io.vertx.reactivex.ext.web.templ.freemarker.FreeMarkerTemplateEngine.create();
|
|
||||||
io.vertx.ext.web.handler.TemplateHandler templateHandler = io.vertx.ext.web.handler.TemplateHandler.create(engine);
|
|
||||||
|
|
||||||
// Create a Routeir
|
|
||||||
Router router = Router.router(vertx);
|
|
||||||
// Mount the handler for all incoming requests at every path and HTTP method
|
|
||||||
|
|
||||||
Database db = new Database(
|
|
||||||
vertx,
|
|
||||||
5432,
|
|
||||||
"localhost",
|
|
||||||
"testdb",
|
|
||||||
"testuser",
|
|
||||||
"123");
|
|
||||||
|
|
||||||
|
|
||||||
router.get("/jsonTest").handler(rc -> {
|
|
||||||
db.executeQuery("SELECT * FROM testtable", rc, Database.OUTPUT_DATATYPE_JSON);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
router.get("/htmlTest").handler(rc -> {
|
|
||||||
db.executeQuery("SELECT * FROM testtable", rc, Database.OUTPUT_DATATYPE_HTML);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
router.get("/dynamic/*").handler(templateHandler);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
router.route().handler(context -> {
|
|
||||||
// Get the address of the request
|
|
||||||
String address = context.request().connection().remoteAddress().toString();
|
|
||||||
// Get the query parameter "name"
|
|
||||||
MultiMap queryParams = context.queryParams();
|
|
||||||
String name = queryParams.contains("name") ? queryParams.get("name") : "unknown";
|
|
||||||
|
|
||||||
|
|
||||||
// Write a json response
|
|
||||||
context.json(
|
|
||||||
new JsonObject()
|
|
||||||
.put("cavecomm", name)
|
|
||||||
.put("address", address)
|
|
||||||
.put("message", "Hello World")
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create the HTTP server
|
|
||||||
vertx.createHttpServer()
|
|
||||||
// Handle every request using the router
|
|
||||||
.requestHandler(router)
|
|
||||||
// Start listening
|
|
||||||
.listen(8888)
|
|
||||||
// Print the port
|
|
||||||
.onSuccess(server ->
|
|
||||||
System.out.println(
|
|
||||||
"HTTP server started on port " + server.actualPort()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
package cavecomm;
|
|
||||||
|
|
||||||
import io.vertx.core.Vertx;
|
|
||||||
import io.vertx.ext.unit.Async;
|
|
||||||
import io.vertx.ext.unit.TestContext;
|
|
||||||
import io.vertx.ext.unit.junit.RunTestOnContext;
|
|
||||||
import io.vertx.ext.unit.junit.VertxUnitRunner;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Rule;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
|
|
||||||
@RunWith(VertxUnitRunner.class)
|
|
||||||
public class TestMainVerticle {
|
|
||||||
|
|
||||||
@Rule
|
|
||||||
public RunTestOnContext rule = new RunTestOnContext();
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void deploy_verticle(TestContext testContext) {
|
|
||||||
Vertx vertx = rule.vertx();
|
|
||||||
vertx.deployVerticle(new MainVerticle(), testContext.asyncAssertSuccess());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void verticle_deployed(TestContext testContext) throws Throwable {
|
|
||||||
Async async = testContext.async();
|
|
||||||
async.complete();
|
|
||||||
}
|
|
||||||
}
|
|
Reference in New Issue
Block a user