custom handle post error - duplicate entry - tastypie

Is it possible to handle a duplicate entry error in a post request so that I can return details of the existing entry rather then an error message?

Yes it is. You'll have to override the obj_create() definition. Here's an example
def obj_create(self, bundle, request=None, **kwargs):
bundle = self.full_hydrate(bundle)
attempt = Attempt.objects.filter(**kwargs)
if attempt.count() < 1:
bundle.obj = Attempt(*kwargs)
else:
logger.info("Updating attempt")
bundle.obj = attempt[0]
return bundle

Related

How to specify file name for a download done via POST in akka http

The user sends a post request, than based on that post body I create an Excel file (.xlsx) and want to send that file back, without storage of that file itself.
def writeAsync(out: OutputStream): Unit = {
Future {
val wb = new XSSFWorkbook
val sheet1: Sheet = wb.createSheet("sheet1");
val os = new ByteArrayOutputStream()
wb.write(os)
os.writeTo(out)
out.close()
wb.close()
}
}
...
pathPrefix("createAndDownloadExcel") {
post {
...
val generatedFileName = "customGeneratedFileName.xlsx" // <-- this name should the file name be like
val (out, source) = StreamConverters.asOutputStream().preMaterialize()
writeAsync(out)
complete(HttpEntity(ContentTypes.`application/octet-stream`, source))
}
}
The response has the excel content with the file name: "createAndDownloadExcel", but I would like it to have the file name based on the individual generated file name.
The name will be later manually generated based on the POST body, whereby a simple change in pathPrefix("fixedName.xlsx") does not work for my needs.
How can I solve this, being able to give a dynamic file name for that returned OutputStream?
"org.apache.poi" % "poi-ooxml" % "5.2.0"
Try adding response header Content-Disposition.
The first parameter in the HTTP context is either inline (default value, indicating it can be displayed inside the Web page, or as the Web page) or attachment (indicating it should be downloaded; most browsers presenting a 'Save as' dialog, prefilled with the value of the filename parameters if present).
import akka.http.scaladsl.model.headers.ContentDispositionTypes.attachment
import akka.http.scaladsl.model.headers.`Content-Disposition`
....
respondWithHeader(`Content-Disposition`(attachment, Map("filename" -> "customGeneratedFileName.xlsx"))) {
complete(HttpEntity(ContentTypes.`application/octet-stream`, source))
}

Getting name of previous test step of type Rest Request in SoapUI groovy script

I'm using groovy script to transfer a certain property from the response of a REST request like this:
def setCookie = testRunner.testCase.testSteps["SubmitCompleteDeviceRegistration"].testRequest.response.responseHeaders["Set-Cookie"]
def global = com.eviware.soapui.SoapUI.globalProperties
re = /(SESSION_AUTHENTICATION_TOKEN=[A-Za-z0-9_-]+;)/
matcher = ( setCookie =~ re )
def cookie = matcher[0][0]
global.setPropertyValue("SESSION_AUTHENTICATION_TOKEN","$cookie")
return cookie
Now what I want to do is make the name of the above teststep, "SubmitCompleteDeviceRegistration", variable, so I can use the transfer for various REST-Requests.
The name of this variable TestStep should equal the name of the previous TestStep of the RestRequest type.
How can I go about defining the TestStep that equals this condition?
I'm trying to use something like
def prevGroovyTestStep =
testRunner.testCase.findPreviousStepOfType(testRunner.testCase.getTestStepByName
("SubmitCompleteDeviceRegistration"),RestRequest)
log.info(prevGroovyTestStep.getName())
But I'm not sure how to implement this.
Any help would be really appreciated!
Getting the previous step name
def previousStepName = context.testCase.testStepList[context.currentStepIndex - 1].name
log.info "Previous step name is : ${previousStepName}"
Getting the previous step name if its type is Rest Request
def testStep = context.testCase.testStepList[context.currentStepIndex - 1]
def previousStepName
if (testStep instanceof com.eviware.soapui.impl.wsdl.teststeps.RestTestRequestStep) {
previousStepName = testStep.name
} else {
log.error "Previous step is not of Rest Request Type"
}
if (previousStepName) {
log.info "Previous step name is : ${previousStepName}"
}
If type does not match in the above case, it will log the error message.
UPDATE - updating as per the latest comments from the author of this question. The below one helps all your need and the above may not needed any more.
Add a custom property for the test case, whose name is STEP_NAME and its value is the test step name to which http header needs to be added. As you commented, the last test step name in this case.
Go the request test step where you are getting the Cookie as response header.
Add an assertion of type Script Assertion and have the below code. Note that, you need to modify the test step name to which you want to add the request header Cookie. Using the place holder for now.
/**Below script should be used as script assertion for first test request step
* Assumes below
* a. test response contains http header called 'Set-Cookie'
* b. other request needs to send http header called 'Cookie'
* In case if there is any change in the two header names you may need to
* change its references below
**/
def responseCookieKey = 'Set-Cookie'
def requestCookieKey = 'Cookie'
def setHttpHeaders(String nextStepName, def headers) {
def nextRequest = context.testCase.testSteps[nextStepName].httpRequest
def existingHeaders = nextRequest.requestHeaders
headers.each {
existingHeaders[it.key] = it.value
}
nextRequest.requestHeaders = existingHeaders
}
if (messageExchange.responseHeaders.containsKey(responseCookieKey)) {
log.info "Found Cookie in the response headers"
def cookiez = messageExchange.responseHeaders[responseCookieKey]
assert null != cookiez, "Response does not contain Cookie"
def headers = [(requestCookieKey) : (cookiez)]
setHttpHeaders(context.testCase.getProvertyValue('STEP_NAME'), headers)
} else {
log.error "Not Found Cookie in the response headers"
}

In a REST API, to GET a resource, should I include the resource ID in the url?

I am trying to create an REST API for creating and retrieving files in my database. The tutorial I was following uses the following method to retrive a single file:
$app->get('/file/:file_id', 'authenticate', function($file_id) {
global $user_id;
$response = array();
$db = new DbHandler();
// fetch file
$result = $db->getFile($file_id, $user_id);
if ($result != NULL) {
$response["error"] = false;
$response["id"] = $result["id"];
$response["file"] = $result["fileLocation"];
$response["status"] = $result["status"];
$response["createdAt"] = $result["created_at"];
echoRespnse(200, $response);
} else {
$response["error"] = true;
$response["message"] = "The requested resource doesn't exist";
echoRespnse(404, $response);
}
});
Here they are using the HTTP GET method and are specifying the file ID in the URL, is it OK to do this, safety wise? Would it not be safer to use POST and hide the file ID in the body of the request, or should they not be putting the file ID in a header with the GET request? or is it not something I should be worried about?
In REST post method is used to create a new resource not to get it. Get method is used for fetching the resource and you need to specify the ID to determine particular resource. Passing it via URL is a common practice. You can randomly generate such ID to make it harder to guess.
As Opal said above, the ID is used to identify a resource. If you are unsure have a read of this - http://blog.teamtreehouse.com/the-definitive-guide-to-get-vs-post

Google sites API, IllegalArgumentException("Trying to set foreign cookie") after RedirectRequiredException

I am using the gdata-media-1.0-1.47.1.jar functionality to fetch media data using the com.google.gdata.client.media.MediaService.getMedia(IMediaContent mediaContent) method. For some requests I get a RedirectRequiredException. When I redo the getMedia request, using the url i get from RedirectRequiredException.getRedirectLocation(), I get an IllegalArgumentException("Trying to set foreign cookie") exception.
From what I can see, the reason for this is that the domain in the response header for the cookie doesn't match the domain of the redirect location. In com.google.gdata.client.http.GoogleGDataRequest.matchDomain() the first argument is ".docs.google.com" and the second is "docs.google.com" which makes the domain matching fail.
Is this a correct behaviour? Why is this happening? Is there something I can do about this? Am I doing anything wrong here? Is is possible to avoid this problem?
SitesService sitesService = new SitesService("SomeAppName");
try {
MediaContent mc = new MediaContent();
mc.setUri(aURI);
return sitesService.getMedia(mc);
} catch (RedirectRequiredException e) {
MediaContent mc = new MediaContent();
mc.setUri(e.getRedirectLocation());
return sitesService.getMedia(mc);
}

using Zend_Gdata_Spreadsheets for public spreadsheets?

I have this code which is working, to load a Google Spreadsheet and load some data from it. If the spreadsheet in question is public, how do i modify the code to not require a username/password?
$key="keytothespreadsheet";
$user="test#example.com";
$pass="*****";
$authService = Zend_Gdata_Spreadsheets::AUTH_SERVICE_NAME;
$httpClient = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $authService);
$gdClient = new Zend_Gdata_Spreadsheets($httpClient);
$query = new Zend_Gdata_Spreadsheets_DocumentQuery();
$query->setSpreadsheetKey($key);
$feed = $gdClient->getWorksheetFeed($query);
print_r($feed);
In the following line, the HTTP client is optional:
$gdClient = new Zend_Gdata_Spreadsheets($httpClient);
So, just don't pass it. The following are equivalent:
$gdClient = new Zend_Gdata_Spreadsheets();
// or
$gdClient = new Zend_Gdata_Spreadsheets(null);
// or
$gdClient = new Zend_Gdata_Spreadsheets(new Zend_Http_Client());
Like #Matt, I wanted to access a public spreadsheet without supplying credentials. Thanks to #Derek Illchuk, I got part of the way there. It still wasn't working, however, until I learned the following:
Note that the File > Publish to the Web feature is not the same thing as Sharing Settings > Public On The Web. If you forget to enable "Publish to the Web", you'll get this error: "Expected response code 200, got 400 The spreadsheet at this URL could not be found. Make sure that you have the right URL and that the owner of the spreadsheet hasn't deleted it."
In the "Publish to the Web" settings, be sure to uncheck "Require viewers to sign in with their ___ account.". Otherwise you'll get this error: "Expected response code 200, got 403 You do not have view access to the spreadsheet. Make sure you are properly authenticated."
According to Google's documentation, "The spreadsheets feed only supports the 'private' visibility and the 'full' projection." However, I found that I needed to specify 'public' visibility and 'basic' projection. Otherwise I got this error:
"Expected response code 200, got 501 Bad or unsupported projection for this type of operation."
Here is what worked for me:
$spreadsheetService = new Zend_Gdata_Spreadsheets(null);
$query = new Zend_Gdata_Spreadsheets_CellQuery();
$query->setSpreadsheetKey($spreadsheetKey);
$query->setWorksheetId($worksheetId);
$query->setVisibility('public'); //options are 'private' or 'public'
$query->setProjection('basic'); //options are 'full' or 'basic'
$cellFeed = $spreadsheetService->getCellFeed($query);
foreach ($cellFeed as $cellEntry) {
$text = $cellEntry->content->text;
//Do something
break; //I only wanted the first cell (R1C1).
}