I am trying to launch a Jenkins parametrized job from a python script. Due to environment requirements, I can't install python-jenkins. I am using raw requests module.
This job I am trying to launch has three parameters:
string (let's call it payload)
string (let's call it target)
file (a file, optional)
I've searched and search, without any success.
I managed to launch the job with two string parameters by launching:
import requests
url = "http://myjenkins/job/MyJobName/buildWithParameters"
target = "http://10.44.542.62:20000"
payload = "{payload: content}"
headers = {"Content-Type": "application/x-www-form-urlencoded"}
msg = {
'token': 'token',
'payload': [ payload ],
'target': [ target ],
}
r = requests.post(url, headers=headers, data=msg)
However I am unable to send a file and those arguments in single request.
I've tried requests.post file argument and failed.
It turns out it is impossible to send both data and file in a single request via HTTP.
import jenkinsapi
from jenkinsHandler import JenkinsHandler
in your python script
Pass parameters to buildJob() , (like < your JenkinsHandler object name>.buildJob())
JenkinsHandler module has functions like init() , buildJob(), isRunning() which helps in triggering the build
Here is an example:
curl -vvv -X POST http://127.0.0.1:8080/jenkins/job/jobname/build
--form file0='#/tmp/yourfile'
--form json='{"parameter": [{"name":"file", "file":"file0"}]}'
--form json='{"parameter": [{"name":"payload", "value":"123"}]
--form json='{"parameter": [{"name":"target", "value":"456"}]}'
Related
I'm learning FastAPI from the official documentation.
When I try running the first example from https://fastapi.tiangolo.com/tutorial/body-multiple-params/ and pasted the URL http://127.0.0.1:8000/items/35 in the browser, my server sends a message
405 Method not allowed
Example code from the link is like below,
from typing import Optional
from fastapi import FastAPI, Path
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: Optional[str] = None
price: float
tax: Optional[float] = None
#app.put("/items/{item_id}")
async def update_item(
*,
item_id: int = Path(..., title="The ID of the item to get", ge=0, le=1000),
q: Optional[str] = None,
item: Optional[Item] = None,
):
results = {"item_id": item_id}
if q:
results.update({"q": q})
if item:
results.update({"item": item})
return results
I understand q and item parameters are optional in this example, so think it can respond with only item_id variable, but it fails.
But if I changed the method to get, which means modified the code with #app.put("/items/{item_id}"), it works.
I want to know what makes this difference.
The main mistake is this:
pasted URL http://127.0.0.1:8000/items/35 in browser, my server sends a message 405 Method not allowed.
Pasting the URL in the browser's address bar sends a GET request, but your route is defined to be called with a PUT request (as explained in the FastAPI tutorial on creating a path operation),
#app.put("/items/{item_id}")
async def update_item(
...
...so the path ("/items/{item_id}") matches but the supported HTTP method does not match (PUT != GET). Hence, the 405 Method Not Allowed error ("the server knows the request method, but the target resource doesn't support this method").
You can see this GET request by opening up your browser's developer console and checking the networking tab (I'm using Firefox in the following screenshot, but the feature should be available in Chrome, Safari, and other browsers):
The simplest way to make a proper PUT request is to use FastAPI's auto-generated interactive API docs. If you are following the tutorial, it should be at http://127.0.0.1:8000/docs. Again, using the developer console you should see it uses the correct HTTP method:
There are a number of alternatives to the interactive API docs.
From the API docs, you can see that each API can be called using the curl command-line utility:
If you are on Linux or Mac, then you can copy-paste that exact command on a terminal/console to call your API (take note of the -X PUT option to specify the correct HTTP method).
~$ curl -i -X 'PUT' \ 'http://127.0.0.1:8000/items/35' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"name": "string",
"description": "string",
"price": 0,
"tax": 0
}'
HTTP/1.1 200 OK
date: Sun, 09 Jan 2022 06:47:33 GMT
server: uvicorn
content-length: 84
content-type: application/json
{"item_id":35,"item":{"name":"string","description":"string","price":0.0,"tax":0.0}}
If you looking for a more programmatic solution, take a look at the requests library or the asynchronous httpx library (which is the same one recommended by FastAPI in its tutorial for testing your routes):
In [24]: import httpx
In [25]: body = {"name":"XYZ", "description":"This is a test.", "price":1.23, "tax":None}
In [26]: r = httpx.put("http://127.0.0.1:8000/items/35", json=body)
In [27]: r.status_code, r.json()
Out[27]:
(200,
{'item_id': 35,
'item': {'name': 'XYZ',
'description': 'This is a test.',
'price': 1.23,
'tax': None}})
In [28]: r = httpx.put("http://127.0.0.1:8000/items/35?q=abc", json=body)
In [29]: r.status_code, r.json()
Out[29]:
(200,
{'item_id': 35,
'q': 'abc',
'item': {'name': 'XYZ',
'description': 'This is a test.',
'price': 1.23,
'tax': None}})
There are also desktop apps that allow you to make these requests using a "nice" UI, such as Postman and Insomnia.
Basically, my point is to stop pasting your API URLs on the browser address bar and instead familiarize yourself with the other ways of making a proper request.
I understand q and item parameters are optional in this example, so think it can respond with only item_id variable, but it fails.
This isn't related to the 405 error.
But if I changed the method to get, which means modified the code with #app.put("/items/{item_id}"), it works.
Yes, since now it will match the browser's GET request. But this is not the solution, especially since that part of the tutorial is talking about updating data (update_item) and a GET request is not the appropriate method for that.
I have ran tika server in my machine and call api using terminal which is working fine. I am able to extract text from image and pdf. But, I want to implement the api call in my python application.
curl -T price.xls http://localhost:9998/tika --header "Accept: text/plain"
Above is api call that i have to make. I can run this in my terminal and works fine but how to implement in python application. I have installed and tried requests.
API_URL = 'http://localhost:9998/tika'
APP_ROOT = os.path.dirname(os.path.abspath(__file__))
tika_client = TikaApp(file_jar=join(APP_ROOT,'../tika-app-1.19.jar'))
data = {
"url": join(APP_ROOT,'../static/image/a.pdf')
}
response = requests.put(API_URL, data)
print(response.content)
Any help will be appreciate. Thank you :)
error output
INFO tika (application/x-www-form-urlencoded)
WARN tika: Text extraction failed
org.apache.tika.exception.TikaException: Unexpected RuntimeException from org.apache.tika.server.resource.TikaResource$1#475b0e2
at org.apache.tika.parser.CompositeParser.parse(CompositeParser.java:282)
at org.apache.tika.parser.AutoDetectParser.parse(AutoDetectParser.java:143)
at org.apache.tika.server.resource.TikaResource.parse(TikaResource.java:402)
at org.apache.tika.server.resource.TikaResource$5.write(TikaResource.java:513)
at org.apache.cxf.jaxrs.provider.BinaryDataProvider.writeTo(BinaryDataProvider.java:177)
at org.apache.cxf.jaxrs.utils.JAXRSUtils.writeMessageBody(JAXRSUtils.java:1391)
at org.apache.cxf.jaxrs.interceptor.JAXRSOutInterceptor.serializeMessage(JAXRSOutInterceptor.java:246)
at org.apache.cxf.jaxrs.interceptor.JAXRSOutInterceptor.processResponse(JAXRSOutInterceptor.java:122)
at org.apache.cxf.jaxrs.interceptor.JAXRSOutInterceptor.handleMessage(JAXRSOutInterceptor.java:84)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
at org.apache.cxf.interceptor.OutgoingChainInterceptor.handleMessage(OutgoingChainInterceptor.java:90)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:267)
at org.apache.cxf.transport.http_jetty.JettyHTTPDestination.doService(JettyHTTPDestination.java:247)
at org.apache.cxf.transport.http_jetty.JettyHTTPHandler.handle(JettyHTTPHandler.java:79)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:257)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1317)
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:205)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1219)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:219)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
at org.eclipse.jetty.server.Server.handle(Server.java:531)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:352)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:260)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:281)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:102)
at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:118)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:333)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:310)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:168)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:126)
at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:366)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:762)
at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:680)
at java.lang.Thread.run(Thread.java:748)
Caused by: javax.ws.rs.WebApplicationException: HTTP 415 Unsupported Media Type
at org.apache.tika.server.resource.TikaResource$1.parse(TikaResource.java:128)
at org.apache.tika.parser.CompositeParser.parse(CompositeParser.java:280)
... 37 more
ERROR Problem with writing the data, class org.apache.tika.server.resource.TikaResource$5, ContentType: text/plain
You need to define the data(payload), header.
url = 'http://localhost:9998/tika/......'
headers = {"Accept: text/plain"}
response = requests.put(url,data = data, headers=headers)
Have glance at this Making a request to a RESTful API using python
I am trying to get the response code for three sites using the below python code snippet. But wondering how I can parse each object in the array to pass through the for loop within the curl call.
import os
servers = ["google", "yahoo", "nonexistingsite"]
for i in range(len(servers)):
print(os.system('curl --write-out "%{http_code}\n" --silent --output'
' /dev/null "https://servers[i].com"'))
With the above code, it's not getting passed through servers[i].
You need to perform string formatting, like:
import os
servers = ["google", "yahoo", "nonexistingsite"]
for server in servers:
print(os.system('curl --write-out "%{{http_code}}\\n" --silent --output /dev/null "https://{}.wellsfargo.com"'.format(server)))
The above can however still go wrong, if for example the servers contain quotes, etc.
It might be better to here use subprocess.run and pass it a list of parameters, like:
servers = ["google", "yahoo", "nonexistingsite"]
for server in servers:
p = subprocess.run(
[
'curl'
'--write-out',
'%{http_code}\\n',
'--silent',
'--output'
'/dev/null',
'https://{}.wellsfargo.com'.format(server)
],
shell=True,
capture_output=True
)
Try using Python's string formatting, something like:
"This string uses an %s" %(argument) would become "This string uses an argument"
Something like this:
print(os.system('curl --write-out "%%{http_code}\n" --silent --output /dev/null "https://%s.wellsfargo.com"') % (servers[i])
More here: https://powerfulpython.com/blog/python-string-formatting/
Just use the requests library instead of shelling out to run curl:
for s in servers:
resp = requests.get(s)
print(resp.status_code)
Since you don't care about the body of the response, only whether it responds, you could save bandwidth by using the head function instead of get to retrieve only the headers from the server.
I'm trying to write a script that imitates a cURL command I make to change data on the target web page:
curl -u username:password "https://website.com/update/" --data "simChangesList=%5B%7B%22simId%22%3A760590802%2C%22changeType%22%3A2%2C%22targetValue%22%3A%220003077%22%2C%22effectiveDate%22%3Anull%7D%5D" --compressed
As you can see above, I am POSTing a url-encoded string to the target web page.
The following code does not work:
import requests
import urllib
enc = urllib.quote('[{"simId":760590802,"changeType":2,"targetValue":000307,"effectiveDate":null}]')
simChangesList = 'simChangesList=' + enc
print simChangesList
auth = s.post(url, data=simChangesList)
print auth.text
Even though I'm fairly certain the above code imitates my cURL command previously, but it obviously isn't.
I am getting a Required List parameter 'simChangesList' is not present error.
What is the equivalent of the cURL command to POST a url-encoded string with the requests module in Python?
EDIT:
I've tried to make multiple dictionaries with simChangesList as the key, but I cannot seem to do it.
Here are my attempts:
simChangesList: [{"simId":760590802,"changeType":2,"targetValue":000307,"effectiveDate":null}]
data = {'simChangesList': ['simId': 760590802, 'changeType': 2, 'targetValue': '0003077', 'effectiveDate': null]}
data['simChangesList'] = ['simId': 760590802, 'changeType': 2, 'targetValue': '0003077', 'effectiveDate': null]
simChangesList:[{"simId":760590802,"changeType":2,"targetValue":"000307","effectiveDate":null}]
payload = {
'simChangesList':
[{'simId': '760590802',
'changeType': '2',
'targetValue': '0003077',
'effectiveDate': 'null'}]
}
I'm connecting to a login protected API with a Python script here below.
import requests
url = 'https://api.json'
header = {'Content-Type': 'application/x-www-form-urlencoded'}
login = ('kjji#snm.com', 'xxxxx')
mnem = 'inputRequests':'{'inputRequests':'[{'function':'GDSP','identifier':'ibm','mnemonic':'IQ_TOTAL_REV'}]}}
r = requests.post(url, auth=login, data=mnem, headers=header)
print(r.json())
The connection is established but I am getting an error from the API because of the format of the data request.The original format is here below. I cannot find a way to enter this in the mnem here above:
inputRequests={inputRequests:
[
{function:"xxx",identifier:"xxx",mnemonic:"xxx"},
]
}
The error given is
C:\Users\xxx\Desktop>pie.py
File "C:\Users\xxx\Desktop\pie.py", line 6
mnem={'inputRequests':'{'inputRequests':'[{'function':'xxx','identifier':'xx','mnemonic':'xxx'}]}}
^
SyntaxError: invalid syntax
I am unsure on how to proceed from here. I cannot find anything in the requests documentation that points to how to insert several variables in the data field.
The requests module in Python receive protogenic Python dict as the JSON data in post request but not a string. Therefore, you may try to define mnem like this:
mnem = {
'inputRequests':[
{'function':'GDSP',
'identifier':'ibm',
'mnemonic':'IQ_TOTAL_REV'
}
]}
the data parameter should be a dictionary.
therefore to pass the three parameters try using:
mnem = {'function':'GDSP','identifier':'ibm','mnemonic':'IQ_TOTAL_REV'}