I made a HTTP request with the following line.
h.request('POST', uri, body,headers={})
I am collecting the response in a variable.
res = h.getresponse()
after that I am trying to print the response by
print(res.msg)
print(res.status)
print(res.read())
After the 3 print statment I am trying to modify the response by storing the res.read() output in a different variable to convert to a string and to do further processing.
text=res.read().decode("utf-8")
But while doing so the decoded response is not getting stored in the variable. If I do a print on text after print(res.read()) it gives me nothing
print(res.read())
text=res.read().decode("utf-8")
print(text)
The output of the above just prints me the first print statement. If I remove the first statement and do the following.
text=res.read().decode("utf-8")
print(text)
It gives me the required O/P. But I wanted both of them to work. So, is there a way to do so.
If you do res.read(), it reads the content of the response during the print statement. On the second execution you cannot read again, unless you seek back or re-do the request.
Store the first .read() in a variable, then print it.
Or u can try following way.
from requests import request
res = request('POST', uri, data,headers={})
print(res.text)
Related
I have a function (api_upload) that accepts a file and HTTP headers, it then sends the file along with the HTTP headers to an API service (example.com/upload), which processes the file, and returns a URL of the processed file.
I am trying to write a unit test for this function (api_upload), and I am feeling a bit lost since this is my first time playing with unit-tests. I have installed pip install requests-mock and also pip install pytest-mock. I guess my question is how do I mock the example.com/upload, because I don't need to actually call example.com/upload in my testing. But I need to test that the function api_upload is "working" as expected.
def api_upload(input_file, headers):
# covert the input_file into a dictionary, since requests library wants a dictionary
input_file = {'file': input_file}
url = 'https://example.com/upload'
files = {'file': open(input_file['file'], 'rb')}
response = requests.post(url, headers=headers, files=files)
saved_file_url = response.json()['url']
return saved_file_url
What I tried is:
def test_api_upload(requests_mock):
requests_mock.get("https://example.com/upload", text='What do I put here?')
#I am not sure what else to write here?
The first thing you need to alter is the (HTTP) method you call. api_upload() does a POST request so that needs to be matched by requests_mock call.
The second thing is that you need to mock the response that the mock would return for your requests.post() call. api_upload() apparently expects JSON that consists of an object with url as one of the attributes. That's what you need to return then.
As to what you should do inside your test function, I'd say:
Mock the POST call and the expected response.
Call api_upload() and give it a mock file (see tmp_path that returns an instance of pathlib.Path).
Assert that the returned URL is what you mocked.
An untested example:
def test_api_upload(requests_mock, tmp_path):
file = tmp_path / "a.txt"
file.write_text("aaa")
mocked_response = {"url": "https://example.com/file/123456789"}
requests_mock.post("https://example.com/upload", json=mocked_response)
assert api_upload(input_file=str(file), headers={}) == mocked_response["url"]
I'm writing a short Python program to request a JSON file using a Rest API call. The API limits me to a relatively small results set (50 or so) and I need to retrieve several thousand result sets. I've implemented a while loop to achieve this and it's working fairly well but I can't figure out the logic for 'continuing the while loop' until there are no more results to retrieve. Right now I've implemented a hard number value but would like to replace it with a conditional that stops the loop if no more results come back. The 'offset' field is the parameter that the API forces you to use to specify which set of results you want in your 50. My logic looks something like...
import requests
import json
from time import sleep
url = "https://someurl"
offsetValue = 0
PARAMS = {'limit':50, 'offset':offsetValue}
headers = {
"Accept": "application/json"
}
while offsetValue <= 1000:
response = requests.request(
"GET",
url,
headers=headers,
params = PARAMS
)
testfile = open("testfile.txt", "a")
testfile.write(json.dumps(json.loads(response.text), sort_keys=True, indent=4, separators=(",", ": ")))
testfile.close()
offsetValue = offsetValue + 1
sleep(1)
So I want to change the conditional the controls the while loop from a fixed number to a check to see if the result set for the getRequest is empty. Hopefully this makes sense.
Your loop can be while true. After each fetch, convert the payload to a dict. If the number of results is 0, then break.
Depending on how the API works, there may be other signals that there’s nothing more to fetch, e.g. some HTTP error, not necessarily the result count — you’ll have to discover the API’s logic for that.
i want to fetch data from cheat.sh using the requests lib and the discord.py lib....but since discord only allows 2000 characters at length to send at a time, i want to fetch only a certain number of words/digits/newline like 1800. how can i do so?
a small bit of code example showing my idea
import requests
url = "https://cheat.sh/python/string+annotations" #this gets the docs of string annotation in python
response = requests.get(url)
data = response.text # This gives approximately 2403 words...but i want to get only 1809 words
print(data)
import requests
url = "https://cheat.sh/python/string+annotations" #this gets the docs of string
annotation in python
response = requests.get(url)
data = response.text[:1800]
print(data)
This will be the correct code
I found pretty cool ASN API tool that allows me to supply an AS # and it will go out and pull down the subnets that relate with that ASN.
Here is (rough) but partial code. I am defining a function ASNNUMBER (to which I will supply the number through another file)
When I call url here, it just gives me an n...
What I'm trying to do here, is append my str(ASNNUMBER) to the end of the ?q= parameter in the URL.
Once I do that, I'd like to display my results and output it to a file
import requests
def asnfinder(ASNNUMBER):
print('n\n######## Running ASNFinder ########\n')
url = 'https://api.hackertarget.com/aslookup?q=' + str(ASNNUMBER)
response = requests.get(url)
My results I'd like to get is an output of the get request I'm performing
## Running ASNFinder
n
Try to write something like that:
import requests
def asnfinder(ASNNUMBER):
print('n\n######## Running ASNFinder ########\n')
url = 'https://api.hackertarget.com/aslookup?q=' + str(ASNNUMBER)
response = requests.get(url)
data = response.text
print(data)
with open('filename', 'r') as f:
f.write(data)
It must works fine
P.S. If it helped ya, please make sure you mark this as the answer :)
I have a SoapUI Mock Service with multiple responses. I want to define a custom sequence for my responses and I do not necessarily use all of the responses in this particular test.
I have actually managed to get this to work in the past, but I think something changed in a newer version of the product and the feature stopped working. That was with a SOAP web service. Now I am mocking a RESTful web service and I have the same requirement to help me do my tests.
The SEQUENCE dispatch option is not what I want, because it will return all of the defined responses in the order in which they were created. The SCRIPT option is what I used previously but now all I can achieve with this is define one response to be generated. For this test I have no interest in examining some content of the request to decide which response to send back.
For example, if I have 8 responses defined, I just want to be able to specify that the following responses are returned:-
Response #2, then Response #3, then Response #4, then finally Response #7; so that Responses #1, #5, #6 and #8 are not used.
My question is posed in detail in the SmartBear forum here:-
simple scripting in a Mock Service - no longer works
I try as you post in the SOAPUI forum using consecutive returns statements with the response order an it doesn't work.
Instead of your groovy code as a DISPATCH script I purpose to use the follow groovy code as workaround, which consist in a use of a list to keep your responses in the desired order and keeping this list in the context an updating it each time using the following code:
// get the list from the context
def myRespList = context.myRespList
// if list is null or empty reinitalize it
if(!myRespList || !myRespList?.size){
// list in the desired output order using the response names that your
// create in your mockservice
myRespList = ["Response 2","Response 3","Response 4","Response 7"]
}
// take the first element from the list
def resp = myRespList.take(1)
// update the context with the list without this element
context.myRespList = myRespList.drop(1)
// return the response
log.info "-->"+resp
return resp
This code works as you expect, since context is keeping the list and each time this script returns the next response and when the list is empty it repopulate it an restart the loop again in the same order.
As an illustration when I use this mockService I get the follow script log:
EDIT
If as OP you've problems with your SOAPUI version because the returned string is between square brackets as ie: [Response 1], change the way that element is taken from the array using:
// take the first element from the list
def resp = myRespList.take(1)[0]
instead of:
// take the first element from the list
def resp = myRespList.take(1)
Note the [0].
With this change the return string will be Response 1 instead of [Response 1].
In this case the script will be:
// get the list from the context
def myRespList = context.myRespList
// if list is null or empty reinitalize it
if(!myRespList || !myRespList?.size){
// list in the desired output order using the response names that your
// create in your mockservice
myRespList = ["Response 2","Response 3","Response 4","Response 7"]
}
// take the first element from the list
def resp = myRespList.take(1)[0]
// update the context with the list without this element
context.myRespList = myRespList.drop(1)
// return the response
log.info "-->"+resp
return resp
Hope this helps,