Creating API gateway in Vlang/vweb - api

I am a new aspiring software developer (currently network engineer/sysadmin) treating Vlang as my first and hopefully main language of choice.
I am trying to build an API gateway for pocketbase.
This is my current code, i want the user to visit /login and then be forwarded to the pocketbase admin instance
module main
import nedpals.vex.server
import nedpals.vex.ctx
import nedpals.vex.router
import net.http
fn main() {
mut app := router.new()
app.route(.get, '/', fn (req &ctx.Req, mut res ctx.Resp) {
http.get('http://localhost:8090/_/#/login') or {}
})
app.route(.get, '/users/:name', fn (req &ctx.Req, mut res ctx.Resp) {
println('path is ${req.params["name"]}')
}, fn (req &ctx.Req, mut res ctx.Resp) {
http.get('path: ' + req.params['name']) or {resp.body}
})
The above code is not working
I tried looking online for some simple examples but i could not find any.
Can someone more experienced assist here?
Thanks
Aimable

Related

How do I return raw bytes in a HTTP Response in Tower Web?

I am developing an API using the tower_web framework, and for some API calls, it would be best to just return bytes with a content type like "application/octet-stream". This data is not directly read from a file, but generated dynamically, so I can't refer to the example code for serving a static file.
For implementing the desired functionality, I tried using a http::Response<Vec<u8>> with a body using a u8 array. Here are the relevant snippets of my code, for testing purposes I used a u8 array filled with zeroes, that would later be the data I want to send to the client:
extern crate tower_web;
use tower_web::ServiceBuilder;
use http::Response as HttpResponse;
const SERVER_ADDRESS : &str = "127.0.0.1:8080";
[...]
#[derive(Clone, Debug)]
pub struct HttpApi;
impl_web! {
impl HttpApi {
[...]
#[get("/test")]
#[content_type("application/octet-stream")]
fn test(&self) -> http::Response<Vec<u8>> {
let response = HttpResponse::builder().status(200).body([0u8;16]);
println!("{:?}", response);
response
}
}
}
pub fn main() {
let addr = SERVER_ADDRESS.parse().expect("Invalid address");
println!("Listening on http://{}", addr);
ServiceBuilder::new()
.resource(HttpApi)
.run(&addr)
.unwrap();
}
However, when I try to build it using cargo, I get this error:
the trait `tower_web::codegen::futures::Future` is not implemented for `http::Response<Vec<u8>>`
I also tried setting the type returned by the function to a Result wrapping the http::Response<Vec<u8>> and (), as it would work that way when I try returning strings or json. This gave me the error
the trait `BufStream` is not implemented for `Vec<u8>`
Is there any simple way to solve this, or any other approach for returning bytes as the body of a HTTP Response in Tower Web?

Rusoto S3 reading object from S3

apologies if this is a dumb question, I am new enough to using rust and i am having a hard time figuring out how to read an object from s3 using the rusoto library.
https://rusoto.github.io/rusoto/rusoto_s3/
so far i've worked out this much:
let mut get_object_request = rusoto_s3::GetObjectRequest::default();
get_object_request.bucket = bucket.to_owned();
get_object_request.key = object_id.to_owned();
let resp = client.get_object(get_object_request)
.await
.map_err(|_| {
FailedToParseFile(format!(
"Failed to retrieve file from s3, bucket: {}, object id: {}",
bucket, object_id
))
})?;
let mut resp_body = match resp.body {
Some(body) => {body}
None => { return Err(ClientError::FailedToObtainConfiguredFile(
format!("Failed to retrieve the file: {} in {}", object_id, bucket)
))}
};
However i've no idea how to turn the streaming body returned from this into a usable string. I've tried a few things to get this working but none seem to work for me.
let mut byte_buffer = String::new();
resp_body.into_blocking_read()
.read_to_string(&mut byte_buffer)
.map_err(|_| {
FailedToParseFile(format!(
"Failed to parse the received file, bucket: {}, object id: {}",
bucket, object_id
))
})?;
let resp_body_bytes = byte_buffer.into_bytes();
As i am using tokio (rocket), this blocking queue doesn't seem to be an option for me causing it to panic on attempting to block on async thread. I started looking at the method 'into_async_read()' rather than blocking but i'm unfamiliar with this too and seem to be struggling using it as intended, this is starting to seem pretty convoluted maybe i'm missing something, any help with this would be appreciated.
let mut byte_buffer = String::new();
Pin::new(&mut resp_body.into_async_read())
.read_to_string(&mut byte_buffer)
.await;
This actually seems to do what I need it to, messing about with this I didn't realise the result of .read_to_string(&mut byte_buffer) could be awaited in order to fill the supplied buffer.

How to reload Go Fiber in the terminal?

I am completely new to this community but would really appreciate if someone can help me with this problem I am facing. I am currently following the basic tutorial of the simple Hello World app but how can we update the code to say something else and that to be updated in our output on the browser in real time?
package main
import (
"log"
"github.com/gofiber/fiber/v2"
)
func main() {
// Fiber instance
app := fiber.New()
// Routes
app.Get("/", hello)
// Start server
log.Fatal(app.Listen(":3000"))
}
// Handler
func hello(c *fiber.Ctx) error {
return c.SendString("Hello, World 👋!")
}
You're talking about hot-reloading (live-reloading). Go itself do not have it implemented by default to achieve that, but you can do it with the package called air https://github.com/cosmtrek/air. Here is a great tutorial how to use it with Fiber: https://dev.to/komfysach/go-live-reload-using-air-40ll

Solana Rust program HashMap<string, u64>

I am trying to port Ethereum DeFi contracts into Solana's Rust programs...
I have learned about saving a struct or an array in programs' account data, but still do not know how to save a HashMap<address in string, amount in u64> into a program's account data...
Then how to read this HashMap's values like checking each address' staked amount.
Please help. Thank you!
My Solana Rust program:
pub fn get_init_hashmap() -> HashMap<&'static str, u64> {
let mut staked_amount: HashMap<&str, u64> = HashMap::new();
staked_amount.insert("9Ao3CgcFg3RB2...", 0);
staked_amount.insert("8Uyuz5PUS47GB...", 0);
staked_amount.insert("CRURHng6s7DGR...", 0);
staked_amount
}
pub fn process_instruction(...) -> ProgramResult {
msg!("about to decode account data");
let acct_data_decoded = match HashMap::try_from_slice(&account.data.borrow_mut()) {
Ok(data) => data,//to be of type `HashMap`
Err(err) => {
if err.kind() == InvalidData {
msg!("InvalidData so initializing account data");
get_init_hashmap()
} else {
panic!("Unknown error decoding account data {:?}", err)
}
}
};
msg!("acct_data_decoded: {:?}", acct_data_decoded);
Solana doesn't expose a HashMap like that. In Solidity, it is common to have a top-level HashMap that tracks addresses to user values.
On Solana a common pattern to replace it would be to use PDAs (Program derived addresses). You can Hash user SOL wallet to ensure unique PDAs and then iterate over them using an off-chain crank.
Answered by Solana dev support on Discord:
HashMap doesnt work on-chain at the moment, so you'll have to use BTreeMap.
As for actually saving it, you can iterate through the key-value pairs and serializing each of those.
In general though, we suggest using mutiple accounts, and program-derived addresses for each account: https://docs.solana.com/developing/programming-model/calling-between-programs#program-derived-addresses

Make nested module public in Rust

I'm starting a project to learn Rust and I fail at the most basic things, like setting up a proper module structure. My code looks like this:
// src/theorem/math.rs
pub mod theorem {
pub mod math {
use std::ops::{Add, Sub};
pub struct Point {
x: i32,
y: i32,
}
impl Add for Point {
// Omitted...
}
}
pub use math::{Point};
}
#[cfg(test)]
mod tests {
use theorem::math::{Point};
#[test]
fn add_point() {
let v1 = Point { x: 1, y: 1 };
let v2 = Point { x: 2, y: 2 };
assert_eq!(v1 + v1, v2);
}
}
I tried pub use, and I tried to write pub in front of everything, everywhere, but all I get is the message
error[E0432]: unresolved import `math::Point`
--> src/theorem/math.rs:28:20
|
28 | pub use math::{Point};
| ^^^^^ no `Point` in `math`
Which is a nice insight but does not help me. I read through the docs but there are no real examples for this case, but... it must be possible, right?
I have also tried to have a proper directory structure like src/theorem/math/point.rs but that did not work either.
What compiler version do you use? Since version 1.13, the error message looks like this:
error[E0432]: unresolved import `math::Point`
--> <anon>:16:20
|
16 | pub use math::{Point};
| ^^^^^ Did you mean `self::math`?
And pub use self::math::{Point}; is in fact the solution to your question! When you use a path, this path is always an absolute path. This means it is interpreted from the root of your crate. But there is no math module as direct child of the root module, hence the error.