rewrote to use C++ instead of Java

This commit is contained in:
2023-03-13 02:32:23 -05:00
parent d43dd509a7
commit 8d9d3df7eb
5 changed files with 110 additions and 237 deletions

110
src/main.cpp Normal file
View 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();
}

View File

@ -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();
}
}

View File

@ -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());
}
}
}

View File

@ -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()
)
);
}
}

View File

@ -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();
}
}