-
Notifications
You must be signed in to change notification settings - Fork 1
feat: rust implementation #19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
5412032
feat: rust implementation
cbrzn 19979f0
chore: fix name in manifest & improve test structure
cbrzn 8876ee1
feat: add ci/cd
cbrzn 6b41915
chore(rust): set version to 0.0.1-beta.1
cbrzn ffdd187
chore: update crate to last version
cbrzn 79c3a33
feat(implementation/rust): support form data in request
cbrzn 597da6d
feat(implementation/rust): support body in request
cbrzn 147b91c
chore(implementation/rust): add test of get with url params
cbrzn 4dd8885
chore: dont import all dependencies from client crate
cbrzn 9d4743d
chore: bump version of crate
cbrzn 1b9a240
chore: remove --allow-dirty flag from release
cbrzn 11699f3
chore: update with latest version of client & improve test structure
cbrzn 75ffc9b
chore: bump version
cbrzn 2586a18
chore: remove codegen step from rust ci/cd
cbrzn 80ddd6e
chore: update yarn lock
cbrzn 2b91794
chore: update polywrap version & remove namespace from import
cbrzn 8e3b873
chore: set v to alpha.1 with new crates name
cbrzn 9772ddd
chore: update client to v 0.1.6-beta.4
cbrzn 034836b
chore: bump version
cbrzn 7bb69c2
chore: update client to v 0.1.6-beta.5 & bump version
cbrzn 73e65c0
chore: move methods from mapping to its own file & update client version
cbrzn File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| name: http-plugin-rs-cd | ||
|
|
||
| on: | ||
| pull_request: | ||
| types: [closed] | ||
| branches: | ||
| - main | ||
| paths: | ||
| - "implementations/rs/**" | ||
|
|
||
| jobs: | ||
| cd: | ||
| name: http-plugin-rs-cd | ||
| if: | | ||
| github.event.pull_request.merged && | ||
| endsWith(github.event.pull_request.title, '/release/rs') && | ||
| github.event.pull_request.user.login != 'github-actions' | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 60 | ||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@v2 | ||
|
|
||
| - name: Read .nvmrc | ||
| run: echo ::set-output name=NVMRC::$(cat .nvmrc) | ||
| id: nvm | ||
|
|
||
| - name: Setup Node.js | ||
| uses: actions/setup-node@master | ||
| with: | ||
| node-version: '${{ steps.nvm.outputs.NVMRC }}' | ||
|
|
||
| - name: Install dependencies | ||
| run: yarn install --nonInteractive --frozen-lockfile --prefer-offline | ||
| working-directory: ./implementations/rs | ||
|
|
||
| - name: Install Rust | ||
| uses: actions-rs/toolchain@v1 | ||
| with: | ||
| toolchain: nightly | ||
| override: true | ||
|
|
||
| - name: Publish | ||
| run: cargo publish --token {{ env.CRATES_TOKEN }} | ||
| working-directory: ./implementations/rs | ||
| env: | ||
| CRATES_TOKEN: ${{ secrets.POLYWRAP_BUILD_BOT_CRATES_PAT }} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| name: http-plugin-rs-ci | ||
|
|
||
| on: | ||
| pull_request: | ||
| paths: | ||
| - "implementations/rs/**" | ||
|
|
||
| jobs: | ||
| ci: | ||
| name: http-plugin-rs-ci | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 60 | ||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@v2 | ||
|
|
||
| - name: Read .nvmrc | ||
| run: echo ::set-output name=NVMRC::$(cat .nvmrc) | ||
| id: nvm | ||
| working-directory: ./implementations/rs | ||
|
|
||
| - name: Setup Node.js | ||
| uses: actions/setup-node@master | ||
| with: | ||
| node-version: '${{ steps.nvm.outputs.NVMRC }}' | ||
|
|
||
| - name: Install dependencies | ||
| run: yarn install --nonInteractive --frozen-lockfile --prefer-offline | ||
| working-directory: ./implementations/rs | ||
|
|
||
| - name: Install Rust | ||
| uses: actions-rs/toolchain@v1 | ||
| with: | ||
| toolchain: nightly | ||
| override: true | ||
|
|
||
| - name: Build | ||
| run: cargo build | ||
| working-directory: ./implementations/rs | ||
|
|
||
| - name: Test | ||
| run: cargo test | ||
| working-directory: ./implementations/rs |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| !src/wrap |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| [package] | ||
| name = "polywrap_http_plugin" | ||
| version = "0.0.1-beta.4" | ||
| license = "MIT" | ||
| description = "Polywrap rust HTTP plugin" | ||
| edition = "2021" | ||
|
|
||
| [dependencies] | ||
| polywrap_core = { version = "0.1.6-beta" } | ||
| polywrap_plugin = { version = "0.1.6-beta" } | ||
| polywrap_msgpack = { version = "0.1.6-beta" } | ||
| polywrap_resolvers = { version = "0.1.6-beta" } | ||
| wrap_manifest_schemas = { version = "0.1.6-beta" } | ||
|
|
||
| ureq = "2.5.0" | ||
| serde = {version = "1.0.145", features = ["derive"]} | ||
| base64 = "0.13.0" | ||
| multipart = "0.17.0" | ||
|
|
||
| [dev-dependencies] | ||
| polywrap_client = { version = "0.1.6-beta" } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| { | ||
| "name": "@polywrap/http-rs", | ||
| "description": "Polywrap HTTP Plugin in Rust", | ||
| "version": "0.1.0", | ||
| "scripts": { | ||
| "codegen": "npx polywrap codegen" | ||
| }, | ||
| "devDependencies": { | ||
| "polywrap": "0.10.3" | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| format: 0.3.0 | ||
| project: | ||
| type: plugin/rust | ||
| name: Http | ||
| source: | ||
| module: ./Cargo.toml | ||
| schema: ./src/schema.graphql |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,131 @@ | ||
| use crate::{wrap::wrap_info::get_manifest, parse_request::parse_request, parse_response::parse_response}; | ||
| use multipart::client::lazy::Multipart; | ||
| use polywrap_core::invoker::Invoker; | ||
| use polywrap_plugin::{error::PluginError, implementor::plugin_impl, JSON}; | ||
| use ureq::{Request as UreqRequest, Response as UreqResponse}; | ||
| use std::{io::Cursor, sync::Arc}; | ||
| use wrap::{ | ||
| module::{ArgsGet, ArgsPost, Module}, | ||
| types::{Response, ResponseType, FormDataEntry}, | ||
| }; | ||
| pub mod wrap; | ||
| pub mod parse_response; | ||
| pub mod parse_request; | ||
|
|
||
| pub enum RequestMethod { | ||
| GET, | ||
| POST, | ||
| } | ||
|
|
||
| #[derive(Debug)] | ||
| pub struct HttpPlugin; | ||
|
|
||
| #[plugin_impl] | ||
| impl Module for HttpPlugin { | ||
| fn get( | ||
| &mut self, | ||
| args: &ArgsGet, | ||
| _: Arc<dyn Invoker>, | ||
| ) -> Result<Option<Response>, PluginError> { | ||
| let response = parse_request(&args.url, args.request.clone(), RequestMethod::GET) | ||
| .unwrap() | ||
| .call() | ||
| .map_err(|e| PluginError::InvocationError { | ||
| exception: e.to_string(), | ||
| })?; | ||
|
|
||
| let response_type = if let Some(r) = &args.request { | ||
| r.response_type | ||
| } else { | ||
| ResponseType::TEXT | ||
| }; | ||
|
|
||
| let parsed_response = parse_response(response, response_type)?; | ||
|
|
||
| Ok(Some(parsed_response)) | ||
| } | ||
|
|
||
| fn post( | ||
cbrzn marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| &mut self, | ||
| args: &ArgsPost, | ||
| _: Arc<dyn Invoker>, | ||
| ) -> Result<Option<Response>, PluginError> { | ||
| let request = parse_request( | ||
| &args.url, | ||
| args.request.clone(), | ||
| RequestMethod::POST, | ||
| ) | ||
| .unwrap(); | ||
|
|
||
| let response_type = if let Some(r) = &args.request { | ||
| r.response_type | ||
| } else { | ||
| ResponseType::TEXT | ||
| }; | ||
|
|
||
| let response = if let Some(r) = &args.request { | ||
| if let Some(body) = &r.body { | ||
| handle_json(request, body)? | ||
| } else if let Some(form_data) = &r.form_data { | ||
| handle_form_data(request, form_data)? | ||
| } else { | ||
| request.call().map_err(|e| PluginError::InvocationError { | ||
| exception: e.to_string(), | ||
| })? | ||
| } | ||
| } else { | ||
| request.call().map_err(|e| PluginError::InvocationError { | ||
| exception: e.to_string(), | ||
| })? | ||
| }; | ||
| let parsed_response = parse_response(response, response_type)?; | ||
|
|
||
| Ok(Some(parsed_response)) | ||
| } | ||
| } | ||
|
|
||
| fn handle_form_data(request: UreqRequest, form_data: &Vec<FormDataEntry>) -> Result<UreqResponse, PluginError> { | ||
| let mut multipart = Multipart::new(); | ||
| for entry in form_data.iter() { | ||
| if entry._type.is_some() { | ||
| if let Some(v) = &entry.value { | ||
| let buf = base64::decode(v).unwrap(); | ||
| let cursor = Cursor::new(buf); | ||
| let file_name = if let Some(f) = &entry.file_name { | ||
| Some(f.as_str()) | ||
| } else { | ||
| None | ||
| }; | ||
| multipart.add_stream(entry.name.as_str(), cursor, file_name, None); | ||
| }; | ||
| } else { | ||
| if let Some(v) = &entry.value { | ||
| multipart.add_text(entry.name.as_str(), v); | ||
| }; | ||
| } | ||
| } | ||
| // Send the request with the multipart/form-data | ||
| let mdata = multipart.prepare().unwrap(); | ||
| request | ||
| .set( | ||
| "Content-Type", | ||
| &format!("multipart/form-data; boundary={}", mdata.boundary()), | ||
| ) | ||
| .send(mdata) | ||
| .map_err(|e| PluginError::InvocationError { | ||
| exception: e.to_string(), | ||
| }) | ||
| } | ||
|
|
||
| fn handle_json(request: UreqRequest, body: &String) -> Result<UreqResponse, PluginError> { | ||
| let value = JSON::from_str::<JSON::Value>(body.as_str()); | ||
| if let Ok(json) = value { | ||
| request | ||
| .send_json(json) | ||
| .map_err(|e| PluginError::InvocationError { | ||
| exception: e.to_string(), | ||
| }) | ||
| } else { | ||
| return Err(PluginError::JSONError(value.unwrap_err())); | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| use polywrap_plugin::error::PluginError; | ||
|
|
||
| use crate::{RequestMethod, wrap::types::Request}; | ||
|
|
||
| pub fn parse_request( | ||
| url: &str, | ||
| request: Option<Request>, | ||
| method: RequestMethod, | ||
| ) -> Result<ureq::Request, PluginError> { | ||
| let mut request_builder = match method { | ||
| RequestMethod::GET => ureq::get(url), | ||
| RequestMethod::POST => ureq::post(url), | ||
| }; | ||
|
|
||
| if let Some(request) = request { | ||
| if let Some(url_params) = request.url_params { | ||
| for (key, value) in url_params.0.iter() { | ||
| request_builder = request_builder.query(key, value); | ||
| } | ||
| }; | ||
|
|
||
| if let Some(headers) = request.headers { | ||
| for (name, value) in headers.0.iter() { | ||
| request_builder = request_builder.set(name, value) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| Ok(request_builder) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| use std::collections::BTreeMap; | ||
|
|
||
| use polywrap_plugin::{Map, error::PluginError}; | ||
|
|
||
| use crate::wrap::types::{ResponseType, Response}; | ||
|
|
||
| pub fn parse_response( | ||
| response: ureq::Response, | ||
| encoding: ResponseType, | ||
| ) -> Result<Response, PluginError> { | ||
| let headers = response | ||
| .headers_names() | ||
| .iter() | ||
| .map(|header_name| { | ||
| ( | ||
| header_name.to_string(), | ||
| response.header(header_name).unwrap().to_string(), | ||
| ) | ||
| }) | ||
| .collect::<BTreeMap<String, String>>(); | ||
| let headers = Map(headers); | ||
| let status = response.status(); | ||
| let status_text = response.status_text().to_string(); | ||
|
|
||
| let mut reader = response.into_reader(); | ||
| let mut data = vec![]; | ||
| reader.read_to_end(&mut data).unwrap(); | ||
|
|
||
| let data = match encoding { | ||
| ResponseType::BINARY => base64::encode(data), | ||
| _ => String::from_utf8_lossy(&data).to_string(), | ||
| }; | ||
|
|
||
| Ok(Response { | ||
| status: status.into(), | ||
| status_text, | ||
| headers: Some(headers), | ||
| body: Some(data), | ||
| }) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| #import * from "ens/wraps.eth:http@1.1.0" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| /// NOTE: This is an auto-generated file. | ||
| /// All modifications will be overwritten. | ||
|
|
||
| pub mod types; | ||
| #[path = "wrap.info.rs"] | ||
| pub mod wrap_info; | ||
| pub mod module; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| /// NOTE: This is an auto-generated file. | ||
| /// All modifications will be overwritten. | ||
|
|
||
| use std::sync::Arc; | ||
| use polywrap_core::invoker::Invoker; | ||
| use polywrap_plugin::{error::PluginError, module::PluginModule}; | ||
| use serde::{Serialize, Deserialize}; | ||
| use super::types::*; | ||
|
|
||
| #[derive(Clone, Debug, Deserialize, Serialize)] | ||
| pub struct ArgsGet { | ||
| pub url: String, | ||
| pub request: Option<Request>, | ||
| } | ||
|
|
||
| #[derive(Clone, Debug, Deserialize, Serialize)] | ||
| pub struct ArgsPost { | ||
| pub url: String, | ||
| pub request: Option<Request>, | ||
| } | ||
|
|
||
| pub trait Module: PluginModule { | ||
| fn get(&mut self, args: &ArgsGet, invoker: Arc<dyn Invoker>) -> Result<Option<Response>, PluginError>; | ||
|
|
||
| fn post(&mut self, args: &ArgsPost, invoker: Arc<dyn Invoker>) -> Result<Option<Response>, PluginError>; | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general for wrappers (like we talked about on the call), I'd love to see more unit tests where we mock the deps (e.g. the subinvocations or in this case the network call).
This not only helps us test the code more thoroughly and without the client dep, but also I find it helps while developing.