I've built a Python application that generates a inventory CSV file, and I want to upload that file to my store through BigCommerce's WebDAV application. I'm using the following Python client to access the WebDAV.
https://pypi.org/project/webdavclient3/
I can access my store and add files to the content folder with CyberDuck, but I get a HTTP 401 error when I try to access it from my Python script. Here is what I'm using to connect with WebDAV.
# webDAV upload to BigCommerce
options = {
'webdav_hostname': "https://mystore.com",
'webdav_login': "email#email.com",
'webdav_password': "password",
'webdav_root': "/dav/",
}
client = Client(options)
print("Exist:", client.check("/content/mytest")) # returns "Exist: False"
print(client.list())
print(client.free())
print("HERE")
I get an error at client.list() that reads
Request to https://mystore.com/dav/ failed with code 401 and message:
<?xml version="1.0" encoding="utf-8"?>
<d:error xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns"><s:exception>Sabre\\DAV\\Exception\\NotAuthenticated</s:exception><s:message>No 'Authorization: Digest' header found. Either the client didn't send one, or the server is misconfigured</s:message>
</d:error>
I guess it's saying my login and/or password is incorrect or there is no authentication? But how come I could log in through CyberDuck with the same credentials?
I saw someone asking about a similar problem in the following link, and I've tried the suggestions from Karen. None of them worked.
https://support.bigcommerce.com/s/question/0D51B00004G4XfYSAV/unable-to-access-upload-files-or-create-directory-through-webdav-api
I know this is 6 months old, but I figured I'd still post the solution for visibility when others try to do this.
The webdavclient library does not support HTTP Digest Authentication which is required to upload to the WebDAV. You can achieve this using the basic Python Requests library combined with the HTTPDigestAuth library.
Sample code:
import requests
from requests.auth import HTTPDigestAuth
# Below, put the URL of your BigCommerce WebDAV, including the file name you want to create/upload
# If you're uploading a CSV that you want to use as a product import, you will put it in the /dav/import_files/ directory.
url='https://store-abcdefg123.mybigcommerce.com/dav/import_files/products_upload_filename.csv' # example
# Local filename relative to this python script to upload
files = open('products_upload_filename.csv', 'rb')
# BigCommerce WebDAV login credentials.
# Found under Server Settings > File Access (WebDAV)
usern = 'youremail#email.com' # username
passw = 'password123' # password
# Make the file upload request
r = requests.request('PUT', url=url, data=files, auth=HTTPDigestAuth(usern, passw))
r.status_code
print(r.headers)
print(r.status_code)
I had the same issue and it was from the AuthType in the VirtualHost (/etc/httpd/conf.d/webdav.conf). I switched from Digest to Basic to fix it.
Related
guys I want to create a python API and request msg and get a response with JSON and send it to knime workflow and work with it
this is my script in python the fact is that he give me json.decoder.jsondecodeError
from importlib.metadata import files
import requests
url ='https://api.edination.com/v2/edifact/read'
headers = {'Ocp-Apim-Subscription-Key': '3ecf6b1c5cf34bd797a5f4c57951a1cf'}
files = {'file':open('C:\\Users\\hcharafeddine\\Desktop\\EDI\\Interchange_1654767219416.edi','rb')}
r = requests.post(url,files=files)
r.json()
We'll need more info to help further. I understand if you don't want to share the content of the EDI message, so here are a few things to try:
The EDINation website allows you to paste an EDI message in and it'll show you the JSON output that the API will return
It also has a sample EDIFACT document you can select and then save locally to run through your python script - you can then share the results here
You can also use HTTPToolkit to inspect the API request and response to troubleshoot further.
I'm trying to fetch metadata from thoughtspot. I am able to call the url using browser and fetch the data. But here I'm trying to achieve it via python program. According to thougthspot documentation. I have to enable trusted authentication and pass my secret key & username to obtain a token which I can use in my program.
https://developers.thoughtspot.com/docs/?pageid=api-auth-session
my username : username#username.com
secret key : secret-key
Below is my code:(generated by postman)
import requests
url = "https://<ThoughtSpot-host>/callosum/v1/tspublic/v1/session/auth/token?auth_token=secret-key&access_level=FULL&username=username#username.com"
payload={}
headers = {}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
I'm getting Bad request error. Anyone here using thoughtspot over this issue. Appreciate your support very much.
Error I'm getting:
{"type":"Bad Request","description":"The server could not understand the request due to invalid syntax."}
I can fetch data by calling the api using a web-browser. Below url returns list of all meta-data objects. I want to achieve this using a python program (I have to authenticate first & call the below URL - Authentication step is not working for me when I tried to follow the documentation)
https://<ThoughtSpot-host>/callosum/v1/tspublic/v1/metadata/list
Did you try changing the url so that it includes the domain name?
Also post the error you are getting. And a screenshot of a working request would be great!
I want to use the Bitbucket API to get information of a private repository.
It works fine with curl:
curl -u username:apppassword https://api.bitbucket.org/2.0/repositories/company/repo
But not with Python (Unfortunately I have to use Python 3.4):
#!/usr/bin/env python3
from pybitbucket.auth import BasicAuthenticator
from pybitbucket.bitbucket import Client
from pybitbucket.repository import Repository
from pybitbucket.user import User
client = Client(BasicAuthenticator('username', 'apppassword ', 'usermail'))
print(User.find_current_user(client).display_name)
print(Repository.find_repository_by_full_name("company/repo"))
User name is printed correctly. But Repository.find_repository_by_full_name raises a 403 (forbidden).
Same thing, when I try to do it with urllib:
import urllib.request
base_url = 'https://api.bitbucket.org/2.0/'
password_mgr = urllib.request.HTTPPasswordMgrWithDefaultRealm()
password_mgr.add_password(None, base_url, 'username', 'apppassword ')
handler = urllib.request.HTTPBasicAuthHandler(password_mgr)
opener = urllib.request.build_opener(handler)
with opener.open(base_url + 'user') as f:
print(f.read())
with opener.open(base_url + 'repositories/company/repo') as f:
print(f.read())
Authentication must work, otherwise it could not return my user name correctly. Also, when I enter wrong credentials, I get a 401 (unauthorized) instead of a 403 (forbidden).
On the other hand, it works perfectly fine when I use curl.
Oh, it doesn't work with wget either:
wget --http-user=username --http-passwd=apppassword https://api.bitbucket.org/2.0/repositories/company/repository
What is curl doing different than wget and Python?
The Bitbucket API doesn't answer with 401 Unauthorized when I call https://api.bitbucket.org/2.0/repositories/company/repository. This can easily tested with a browser. It doesn't ask for credentials but shows Access denied. You must have write or admin access. So no authentication will take place.
But when I open https://api.bitbucket.org/2.0/user, Bitbucket responses with 401 Unauthorized and the header www-authenticate: Basic realm="Bitbucket.org HTTP", so the browser knows to show the authentication dialog. That's why getting the user data works on Python.
To solve this, I have to enforce to send the authentication even when the server doesn't ask for it. I haven't found a way to do this with a urllib.request.HTTPBasicAuthHandler but by adding the Authorization header manually:
import base64
import urllib.request
request = urllib.request.Request('https://api.bitbucket.org/2.0/repositories/company/repository')
base64string = base64.b64encode('{}:{}'.format('username', 'apppassword').encode('ascii'))
request.add_header('Authorization', 'Basic {}'.format(base64string.decode('ascii')))
with urllib.request.urlopen(request) as response:
print(response.read())
I have been working on using the powerbi REST API and I haven't been able to properly make use of it. I made use of this and I was able to register an app and get as far as getting an access token, but still I get 401 statuses on my requests.
My major points of confusion are with regards to the app registration:
1) I am trying to read and write data from a python script. Is this a Native-App or a Web Side Server?
2) What is the meaning of the redirect and home urls on the app registration page? I am currently using my localhost:5000 with different /paths. Could this be the source of the issue?
3) My research indicates that there should be some sort of login interaction. I don't have one, is this an indication that something isn't being done properly?
My code is as follows:
import adal
import requests
AUTHORITY_URL = 'https://login.microsoftonline.com/{my_company}.onmicrosoft.com'
RESOURCE = 'https://analysis.windows.net/powerbi/api'
CLIENT_ID = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
CLIENT_SECRET = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
def make_headers(access_token):
return {
'Authorization': "Bearer {}".format(access_token)
}
context = adal.AuthenticationContext(AUTHORITY_URL)
token = context.acquire_token_with_client_credentials(RESOURCE, CLIENT_ID, CLIENT_SECRET)
access_token = token['accessToken']
headers = make_headers(access_token)
url = "https://api.powerbi.com/v1.0/myorg/datasets"
resp = requests.get(url, headers=headers)
As I said above this works to give me an access token though a get a status 401 response on the request and there is no sign in prompt.
Any help/guidance would be tremendously appreciated.
1) In your case you should register a Native app.
2) Native apps has only Redirect URI. Redirect URI gives AAD more details about the specific application it authenticates. For Native apps you should set it to https://login.live.com/oauth20_desktop.srf.
3) It's hard to say why you are getting Unauthorized response. Check what rights you gave to your application - does it has rights to read or write all datasets? Try to decode the access token at https://jwt.io and look at scp - does it contain "Dataset.Read.All" or "Dataset.ReadWrite.All"?
Working with the Streak CRM API by using Python and Request. I am getting 4XX errors depending on how I phrase the request. (Examples below)
response = requests.get('https://www.streak.com/api/v1/pipelines?api-key=xxxxxxxx')
response.headers['Content-Type'] = 'application/json'
print(response.status_code)
print(response.content)
Result: 401 "Authentication Required for Streak API: try HTTP Basic Auth or cookie auth"
If I add ".json" after the file path:
requests.get('https://www.streak.com/api/v1/pipelines.json?api-key=xxxxxxxx')
Result: 400 "Invalid API path specified" So I am assuming that I was authenticated but just have a poorly defined file path.
But if I use the same file path and credentials entered in the terminal:
curl https://www.streak.com/api/v1/pipeline -u xxxxxxxx:
Works like a charm.
Why would the file path work in the terminal but not in python? Why do I need to add .json to my file path? New to using APIs so any help is appreciated. Thanks.
I don't know why, but rephrasing it like below worked. I received status code 200:
response = requests.get('https://www.streak.com/api/v1/pipelines', auth=('xxxxxx',''))
The API key goes in the username parameter, and the password parameter is left blank.
The error message tells you all you need to know. For Basic Auth you put the authorization info in the request headers, not in the url. When you add .json to a endpoint, that usually means that you want a JSON response. The reason why it worked with curl is because curl's -u flag is setting the Auth header.