I tried to create a zeep client and use it by two methods.
1) I tried to keep everything in a single module . i created the zeep client object and it was working fine while using a payload.
2) I created a method which returns a zeep client object for a wsdl. I tried to use this a way as method 1) But getting the below error.
zeep.exception.Fault : Incoming message could not be authenticated. No valid credentials found
Can someone please advise what I am missing here which causes this error. My second approach is like this.
\\
def zeepClient(wsdl):
## do all here and return zeep client object.
return client
#Now in another module I do call that above method like this
Client=othermodule.zeepClient(mywsdl)
Payload={my payload}
Client.service.myservice(**Payload)
\\
If I do this , I get above error.But if my above piece of code and my method for zeepClient are all in same place. I am not getting error.
Not sure . What that Returned Client object is missing.
You must provide credentials to the session and then make a request like here
from requests import Session
from requests.auth import HTTPBasicAuth # or HTTPDigestAuth, or OAuth1, etc.
from zeep import Client
from zeep.transports import Transport
session = Session()
session.auth = HTTPBasicAuth(user, password)
client = Client('http://my-endpoint.com/production.svc?wsdl',
transport=Transport(session=session))
Related
I am making python wrapper for some web api service.
I have faced a problem, which I do not how to solve and quite can not understand.
I need to save authorized session object. But I get error:
import pickle
from oauthlib.oauth2 import BackendApplicationClient
from requests_oauthlib import OAuth2Session
client = BackendApplicationClient(client_id="some_id")
oauth_session = OAuth2Session(client=client)
with open("./oauth_session.pkl", "wb") as file:
pickle.dump(oauth_session, file)
# AttributeError: Can't pickle local object
# 'OAuth2Session.__init__.<locals>.<lambda>'
Oauth session according to documentation inherits from requests.Session, which is pickled fine
import pickle
from requests import Session
session = Session()
with open("./session.pkl", "wb") as file:
pickle.dump(session, file)
# Process finished with exit code 0
I have two questions:
Why OAuth session can not be pickled? What's wrong with lambdas?
What is way around it?
My way around was to store only token from session, but it have showed itself unreliable and not working properly with Authorization Code Flow.
Also i tried to use dill, it helped to dump session object by when I load session object back, it seems to be losing session attributes:
like that AttributeError: 'OAuth2Session' object has no attribute '_client'
I found on SO similliar question but answer is for specific external library and not explains anything.
I've been trying to figure out how to properly do a POST with FastAPI.
I'm currently doing a POST with python's "requests module" and passing some json data as shown below:
import requests
from fastapi import FastAPI
json_data = {"user" : MrMinty, "pass" : "password"} #json data
endpoint = "https://www.testsite.com/api/account_name/?access_token=1234567890" #endpoint
print(requests.post(endpoint, json=json_data). content)
I don't understand how to do the same POST using just FastAPI's functions, and reading the response.
The module request is not a FastAPI function, but is everything you need,
first you need to have your FastAPI server running, either in your computer or in a external server that you have access.
Then you need to know the IP or domain of your server, and then you make the request:
import requests
some_info = {'info':'some_info'}
head = 'http://192.168.0.8:8000' #IP and port of your server
# maybe in your case the ip is the localhost
requests.post(f'{head}/send_some_info', data=json.dumps(tablea))
# "send_some_info" is the address of your function in fast api
Your FastApI script would look like this, and should be running while you make your request:
from fastapi import FastAPI
app = FastAPI()
#app.post("/send_some_info")
async def test_function(dict: dict[str, str]):
# do something
return 'Success'
I have an XML/WCF API I need to implement something against. The API client library is only provided as c# in Windows and our company does not do either c# or Windows. I am now experimenting with Python and zeep. The api is Symmetry access control system API if anyone is interested.
I can connect to the server and read the wsdl structure. This works:
URL='https://localhost/smsXMLWebService/SMSXMLWebService.svc?singleWsdl'
URL2='https://localhost/smsXMLWebService/smsXMLWebService.svc'
session = Session()
session.verify = False
transport = Transport(session=session)
self.client = zeep.Client(URL, transport=transport)
self.service = self.client.create_service('{http://tempuri.org/}WSHttpBinding_ISMSXMLWebService', URL2)
Now everything from that point forward will require login to the platform. In the example c# code this is done as follows:
G4TAPI = new SMSXMLWebServiceClient();
G4TAPI.ClientCredentials.UserName.UserName = txtUserName.Text
G4TAPI.ClientCredentials.UserName.Password = txtPassword.Text.ToLower();
G4TAPI.G4TLogin();
My self.service has now G4TLogin() call and it seems to attempt to connect when I wireshark the traffic. But how do I set the username and password as they are not given as parameters to G4TLogin() method?
This does not work:
self.service.ClientCredentials.UserName.UserName = "api"
This is very much out of my comfort zone and I may be using incorrect terminology here. Any ideas?
The error message is
AttributeError: Service has no operation 'ClientCredentials'
When using Zeep make sure to study the namespaces in WSDL URL, using
python -mzeep "YourWsdlUrlGoesHere"
Get the parameters and make a Python dictionary from them (in my case facing C#, including username and password in the dictionary) note that one might need to make nested dictionary like in my case.
from requests import Session
from requests.auth import HTTPBasicAuth, HTTPDigestAuth
from zeep import Client
from zeep.transports import Transport
request = { "Credential":{"Username": "yourusername",
"Password": "yourpassword"},
"RN": "150147119"
}
session = Session()
client = Client('http://your url and wsdl../Invoice.svc?Wsdl',transport=Transport(session=session))
r = client.service.NameOfYourService(request)
print(r)
Do not pass user and password in Zeep formal format. Passing the dictionary worked for me.
In my case the WSDL suggested user and password be in credential and a string be passed in RN and finally all be passed in a one variable.
I have two separate WSDL files that are provided to me to interact with a service, one WSDL file just provides a method to login and generate an access token. The other WSDL file provides the methods to actually interact with the system.
If I instantiate the zeep SOAP client with the first WSDL file to login do I need to reinstantiate the client for the next WSDL file or can I simply tell it to go look at the next WSDL file?
from zeep import Client
client = Client("https://url.service.com/Session?wsdl")
token = client.service.login(username, password)
client = Client("https://url.service.com/Object?wsdl")
client.service.find(token, 'filter')
I attempted to use create_service but I don't think I'm using it correctly.
Thank you!
You need to reinstantiate the second Client.
I expect that you also need to extend your code to use the same requests Session and Zeeps Transport.
from requests import Session
from zeep import Client
from zeep.transports import Transport
transport = Transport(session=Session())
client = Client("https://url.service.com/Session?wsdl", transport=transport)
token = client.service.login(username, password)
client = Client("https://url.service.com/Object?wsdl", transport=transport)
client.service.find(token, 'filter')
I have a python script that calls the Amazon SES api using boto3. It works when I create the client like this client = boto3.client('ses') and allow the aws credentials to come from ~/.aws/credentials, but I wanted to pass the aws_access_key_id and aws_secret_access_key into the constructor somehow.
I thought I had found somewhere that said it was acceptable to do something like this
client = boto3.client(
'ses',
aws_access_key_id=kwargs['aws_access_key_id'],
aws_secret_access_key=kwargs['aws_secret_access_key'],
region_name=kwargs['region_name']
)
but then when I try to send an email, it tells me that there is a TypeError: sequence item 0: expected string, tuple found when it tries to return '/'.join(scope) in botocore/auth.py (line 276).
I know it's a bit of a long shot, but I was hoping someone had an idea of how I can pass these credentials to the client from somewhere other than the aws credentials file. I also have the full stack trace from the error, if that's helpful I can post it as well. I just didn't want to clutter up the question initially.
You need to configure your connection info elsewhere and then connect using:
client = boto3.client('ses', AWS_REGION)
An alternative way, using Session can be done like this:
from boto3.session import Session
# create boto session
session = Session(
aws_access_key_id=settings.AWS_ACCESS_KEY_ID,
aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY,
region_name=settings.AWS_REGION
)
# make connection
client =session.client('s3')