I am trying to get data over an OpenWeather API in Rust but I am facing some iusse regarding parsing I guess - api

extern crate openweather;
use openweather::LocationSpecifier;
static API_KEY: &str = "e85e0a3142231dab28a2611888e48f22";
fn main() {
let loc = LocationSpecifier::Coordinates {
lat: 24.87,
lon: 67.03,
};
let weather = openweather::get_current_weather(loc, API_KEY).unwrap();
print!(
"Right now in Minneapolis, MN it is {}K",
weather.main.humidity
);
}
error : thread 'main' panicked at 'called Result::unwrap() on an
Err value: ErrorReport { cod: 0, message: "Got unexpected response:
\"{\\"coord\\":{\\"lon\\":67.03,\\"lat\\":24.87},\\"weather\\":[{\\"id\\":803,\\"main\\":\\"Clouds\\",\\"description\\":\\"broken
clouds\\",\\"icon\\":\\"04n\\"}],\\"base\\":\\"stations\\",\\"main\\":{\\"temp\\":294.15,\\"pressure\\":1018,\\"humidity\\":60,\\"temp_min\\":294.15,\\"temp_max\\":294.15},\\"visibility\\":6000,\\"wind\\":{\\"speed\\":5.1,\\"deg\\":30},\\"clouds\\":{\\"all\\":70},\\"dt\\":1574012543,\\"sys\\":{\\"type\\":1,\\"id\\":7576,\\"country\\":\\"PK\\",\\"sunrise\\":1573955364,\\"sunset\\":1573994659},\\"timezone\\":18000,\\"id\\":1174872,\\"name\\":\\"Karachi\\",\\"cod\\":200}\""
}

The issue is a JSON parsing error due to the deserialized struct not matching OpenWeather's JSON, perhaps the API recently added this? With your example, the OpenWeatherCurrent struct is missing timezone.
But it looks like there is an open PR that will fix this, you can test it by doing the following:
Change your Cargo.toml dependency to openweather = { git = "https://github.com/caemor/openweather" }.
The PR author has also updated the get_current_weather signature so you'll need to change lines 2, 10 to the following:
use openweather::{LocationSpecifier, Settings};
let weather = openweather::get_current_weather(&loc, API_KEY, &Settings::default()).unwrap();

Related

Call fetchgit without SSL Verify

I'm trying to use fetchgit to download source repos from my lab's private GitLab server, which currently self-signs its SSL certificate.
default.nix:
with (import <nixpkgs> {});
{ test-pkg = callPackage ./test-pkg.nix {
buildPythonPackage = python35Packages.buildPythonPackage;
};
}
test-pkg.nix:
{ buildPythonPackage,fetchgit }:
buildPythonPackage rec {
pname = "test-pkg";
version = "0.2.1";
src = fetchgit {
url = "https://gitlabserver/experiment-deployment/test-pkg";
rev = "refs/tags/v${version}";
sha256 = "43c2c9e5e7a16b6c88ba3088a9bfc82f7db8e13378be7c78d6c14a5f8ed05afd";
};
}
Which results in the error when I call nix-shell
fatal: unable to access 'https://gitlabserver/experiment-deployment/test-pkg/': SSL certificate problem: self signed certificate
Looking at, build-support/fetchgit, it seems that fetchgit is made with mkDerivation, so I tried to make a new fetchgit using overrideAttrs. I pass in the git environment variable to make git ignore SSL verification, expecting that the variable will be initialized during the setup phase.
revised default.nix:
with (import <nixpkgs> {});
let fetchgit-no-verify = fetchgit.overrideAttrs { GIT_SSL_NO_VERIFY=true;} ;
in rec {
test-pkg = callPackage ./test-pkg.nix {
buildPythonPackage = python35Packages.buildPythonPackage;
fetchgit = fetchgit-no-verify;
};
}
I thought I was really clever when I thought of this over the weekend, only to discover that when implemented my new error states that
error: attribute 'overrideAttrs' missing, at [...]/default.nix:2:26
Inspecting fetchgit in nix repl shows that it is a functor attribute set. I tried for a little bit to get to the overrideAttrs, without success. Trying again I saw that git could be passed to to fetchGit,
re-revised default.nix:
with (import <nixpkgs> {});
let git = git.overrideAttrs { GIT_SSL_NO_VERIFY=true;} ;
fetchgit-no-verify = fetchgit.override { git=git-no-verify;} ;
in rec {
test-pkg = callPackage ./test-pkg.nix {
buildPythonPackage = python35Packages.buildPythonPackage;
fetchgit = fetchgit-no-verify;
};
}
but the new error:
error: attempt to call something which is not a function but a set, at /nix/store/jmynn33vcn3mcscsch0zf46fz9wsw05y-nixpkgs-20.03pre193309.c4196cca9ac/nixpkgs/pkgs/stdenv/generic/make-derivation.nix:318:55
Finally, onto my questions. Is there a way to add the environment variable to the fetchgit or git derivations? Is there perhaps another way to connect--some builtin option I missed? I could use a private repository, using ssh and avoiding https, however due to how we deploy experiments I'd like to avoid that.
I was able to make this work with this ugly thing.
default.nix:
with (import <nixpkgs> {});
let fetchgit-no-verify = fetchgit // {
__functor = self : args :
(fetchgit.__functor self args).overrideAttrs (oldAttrs:{GIT_SSL_NO_VERIFY=true;});
} ;
in rec {
test-pkg = callPackage ./test-pkg.nix {
buildPythonPackage = python35Packages.buildPythonPackage;
fetchgit = fetchgit-no-verify;
};
}
fetchgit-no-verify uses the fetchgit functor set to begin with and overwrites the __functor attribute with a new function. The new functor just applies its arguments and then calls overrideAttrs.
This works, but I'm happy to award the answer to anybody who can add some insight or comes with another solution. For one, I'd like to know how the fetchgit derivation becomes a functor. Is this something callPackage does?.

poloniex API request BUY SELL CANCEL cause error = "Invalid API key/secret pair.";

Hello To every one I am writing in swift 3 trading app. I have problem only with 3 commands buy sell and cancel , that ones cause error = "Invalid API key/secret pair."; others like returnOpenOrders , returnTradehistory returnBalances works fine and returns proper values.
That is may request function :
func getRawJSON(paramss:[String : Any]){
var paramss1:[String:Any] = [:]
let APIURL = "https://poloniex.com/tradingApi"
let timeNowInt = Int(NSDate().timeIntervalSince1970 ) * 10000000
var zdanie2:String! = ""
for (x,y) in paramss{
paramss1[x]=y
}
paramss1["nonce"]=timeNowInt
for (x,y) in paramss{
if (zdanie2 == "")
{zdanie2="\(x)=\(y)"
}
else
{
zdanie2=zdanie2+"&"+"\(x)=\(y)"
}
}
zdanie2=zdanie2+"&nonce=\(timeNowInt)"
let array: [UInt8] = Array(zdanie2.utf8)
let hmac: Array<UInt8> = try! HMAC(key: secretKey!.utf8.map({$0}), variant: .sha512).authenticate(array)
let hmacData = Data(bytes: hmac).toHexString()
let headers = ["Key": publicKey!,"Sign": hmacData] as [String : String]
request(APIURL,method: .post,parameters: paramss1,headers:headers).responseJSON {
response in
print(response)
print(response.request)
}
}
Here is my buy/sell function :
func buy(currencyPair:String,rate:Double,amount:Double){
return self.getRawJSON( paramss: ["command":"buy","currencyPair":currencyPair,"rate":rate ,"amount":amount])
}
func sell(currencyPair:String,rate:Double,amount:Double){
return self.getRawJSON( paramss: ["command":"sell","currencyPair":currencyPair,"rate": rate ,"amount":amount])
}
The output from headers parameters(var paramss1 ) is :
["amount": 2.0, "command": "sell", "nonce": 15308121310000000, "currencyPair": "BTC_XRP", "rate": 7.6000000000000004e-05]
The array for sign is :
amount=2.0&command=sell&currencyPair=BTC_XRP&rate=7.6e-05&nonce=15308121310000000
I really dont know what is wrong
Can you help with this problem ??
rate value is invalid.
rate and amount values must be like 1, 1.1, 1.00000001.
Invalid request:
amount=2.0&command=sell&currencyPair=BTC_XRP&rate=7.6e-05&nonce=15308121310000000
Valid request:
command=sell&amount=2.0&&currencyPair=BTC_XRP&rate=7.000006&nonce=15308121310000000

Corda: Party rejected session request as Requestor has not been registered

I've a Corda application that using M14 to build and run corda to run a TwoPartyProtocol where either parties can exchange data to reach a data validity consensus. I've followed Corda flow cookbook to build a flow.
Also, after reading the docs from several different corda milestones I've understood that M14 no longer needs flowSessions as mentioned in the release notes which also eliminates need to register services.
My TwoPartyFlow with inner FlowLogics:
class TwoPartyFlow{
#InitiatingFlow
#StartableByRPC
open class Requestor(val price: Long,
val otherParty: Party) : FlowLogic<SignedTransaction>(){
#Suspendable
override fun call(): SignedTransaction {
val notary = serviceHub.networkMapCache.notaryNodes.single().notaryIdentity
send(otherParty, price)
/*Some code to generate SignedTransaction*/
}
}
#InitiatedBy(Requestor::class)
open class Responder(val requestingParty : Party) : FlowLogic<SignedTransaction>(){
#Suspendable
override fun call(): SignedTransaction {
val request = receive<Long>(requestor).unwrap { price -> price }
println(request)
/*Some code to generate SignedTransaction*/
}
}
}
But, running the above using startTrackedFlow from Api causes the above error:
Party CN=Other,O=Other,L=NY,C=US rejected session request: com.testapp.flow.TwoPartyFlow$Requestor has not been registered
I had hard time finding the reason from corda docs or logs since Two Party flow implementations have changed among several Milestones of corda. Can someone help me understand the problem here.
My API Call:
#GET
#Path("start-flow")
fun requestOffering(#QueryParam(value = "price") price: String) : Response{
val price : Long = 10L
/*Code to get otherParty details*/
val otherPartyHostAndPort = HostAndPort.fromString("localhost:10031")
val client = CordaRPCClient(otherPartyHostAndPort)
val services : CordaRPCOps = client.start("user1","test").proxy
val otherParty: Party = services.nodeIdentity().legalIdentity
val (status, message) = try {
val flowHandle = services.startTrackedFlow(::Requestor, price, otherParty)
val result = flowHandle.use { it.returnValue.getOrThrow() }
// Return the response.
Response.Status.CREATED to "Transaction id ${result.id} committed to ledger.\n"
} catch (e: Exception) {
Response.Status.BAD_REQUEST to e.message
}
return Response.status(status).entity(message).build()
}
My Gradle deployNodes task:
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['build']) {
directory "./build/nodes"
networkMap "CN=Controller,O=R3,OU=corda,L=London,C=UK"
node {
name "CN=Controller,O=R3,OU=corda,L=London,C=UK"
advertisedServices = ["corda.notary.validating"]
p2pPort 10021
rpcPort 10022
cordapps = []
}
node {
name "CN=Subject,O=Subject,L=NY,C=US"
advertisedServices = []
p2pPort 10027
rpcPort 10028
webPort 10029
cordapps = []
rpcUsers = [[ user: "user1", "password": "test", "permissions": []]]
}
node {
name "CN=Other,O=Other,L=NY,C=US"
advertisedServices = []
p2pPort 10030
rpcPort 10031
webPort 10032
cordapps = []
rpcUsers = [[ user: "user1", "password": "test", "permissions": []]]
}
There appears to be a couple of problems with the code you posted:
The annotation should be #StartableByRPC, not #StartableNByRPC
The price passed to startTrackedFlow should be a long, not an int
However, even after fixing these issues, I couldn't replicate your error. Can you apply these fixes, do a clean re-deploy of your nodes (gradlew clean deployNodes), and see whether the error changes?
You shouldn't be connecting to the other node via RPC. RPC is how a node's owner speaks to their node. In the real world, you wouldn't have the other node's RPC credentials, and couldn't log into the node in this way.
Instead, you should use your own node's RPC client to retrieve the counterparty's identity:
val otherParty = services.partyFromX500Name("CN=Other,O=Other,L=NY,C=US")!!
See an M14 example here: https://github.com/corda/cordapp-example/blob/release-M14/kotlin-source/src/main/kotlin/com/example/api/ExampleApi.kt.

how to Pass Raw Json to post request in Swift?

Hi I am new to swift please spare me.
I need to post to particular API but the api is not a fan of key value pair the api expect raw json as post data
I use this library here to make post request.
this is my code
func postItem(itemname: String, itemnumber: Int, itemcode:String, url:String, baseURL:String, completion: (result: Dictionary<String, AnyObject>) -> ()){
var dict: Dictionary<String, AnyObject>!
var params: Dictionary<String,AnyObject> = ["parentItem": ["itemname":itemname,"itemnumber":itemnumber,"itemcode":code]]
let data = NSJSONSerialization.dataWithJSONObject(params, options: NSJSONWritingOptions.PrettyPrinted, error: nil)
let string = NSString(data: data!, encoding: NSUTF8StringEncoding)
var request = HTTPTask()
request.requestSerializer = JSONRequestSerializer()
request.requestSerializer.headers[headerKey] = getToken() //example of adding a header value
request.POST(url, parameters: params, success: {(response: HTTPResponse) in
if response.responseObject != nil {
let data = response.responseObject as NSData
var error: NSError?
dict = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &error) as Dictionary<String, AnyObject>;
completion(result: dict)
}
},failure: {(error: NSError, response: HTTPResponse?) in
dict = ["error" : "error" ]
completion(result: dict)
})
}
i need to pass this kind of raw json in api
eg. {"parentItem": {"itemname":"Cocoa","itemnumber":123,"itemcode":"cocoa-12-A"}}
but when I println my params because it is dictionary it generate something like
["parentItem": ["itemname"="Cocoa"; "itemnumber"=123; "itemcode"="cocoa-12-A"]]
I just couldn't convert the params to JSON because the library I'm using is expecting dictionary and I'm having a hard time creating my own class.
could anyone help me? any comments and suggestion would do. Thanks in advance.
Why don't use Alamofire framework ? It's pretty good and sends standard json

How to pass same parameter with different value

I am trying the following API using Alamofire, but this API has multiple "to" fields. I tried to pass an array of "to" emails as parameters. It shows no error but did not send to all emails. API is correct, I tested that from terminal. Any suggestions will be cordially welcomed.
http -a email:pass -f POST 'sampleUrl' from="email#email.com" to="ongkur.cse#gmail.com" to="emailgmail#email.com" subject="test_sub" bodyText="testing hello"
I am giving my code:
class func sendMessage(message:MessageModel, delegate:RestAPIManagerDelegate?) {
let urlString = "http://localhost:8080/app/user/messages"
var parameters = [String:AnyObject]()
parameters = [
"from": message.messageFrom.emailAddress
]
var array = [String]()
for to in message.messageTO {
array.append(to)
}
parameters["to"] = array
for cc in message.messageCC {
parameters["cc"] = cc.emailAddress;
}
for bcc in message.messageBCC {
parameters["bcc"] = bcc.emailAddress;
}
parameters["subject"] = message.messageSubject;
parameters["bodyText"] = message.bodyText;
Alamofire.request(.POST, urlString, parameters: parameters)
.authenticate(user: MessageManager.sharedInstance().primaryUserName, password: MessageManager.sharedInstance().primaryPassword)
.validate(statusCode: 200..<201)
.validate(contentType: ["application/json"])
.responseJSON {
(_, _, jsonData, error) in
if(error != nil) {
println("\n sendMessage attempt json response:")
println(error!)
delegate?.messageSent?(false)
return
}
println("Server response during message sending:\n")
let swiftyJSONData = JSON(jsonData!)
println(swiftyJSONData)
delegate?.messageSent?(true)
}
}
First of all if you created the API yourself you should consider changing the API to expect an array of 'to' receivers instead of multiple times the same parameter name.
As back2dos states it in this answer: https://stackoverflow.com/a/1898078/672989
Although POST may be having multiple values for the same key, I'd be cautious using it, since some servers can't even properly handle that, which is probably why this isn't supported ... if you convert "duplicate" parameters to a list, the whole thing might start to choke, if a parameter comes in only once, and suddendly you wind up having a string or something ...
And I think he's right.
In this case I guess this is not possible with Alamofire, just as it is not possible with AFNetworking: https://github.com/AFNetworking/AFNetworking/issues/21
Alamofire probably store's its POST parameter in a Dictionary which doesn't allow duplicate keys.