I have a system that is developed in cakephp. There I have a customer profile page that shows me different information like e.g notes, phone calls, attached files. The basic information are fetched via Cakephp other information like the above are fetched via Ajax Requests and shown as soon as the data is fetched.
Unfortunately, sometimes and very randomly (between every 10th and 100th request), I get a 302 of an Ajax Request and will logged out and redirected to the login formular (which is the basic redirection path if you are not logged in).
You can see an example from the Google network page in the pictures. The picture shows that the calls getPhonecalls, getNotes and getOutboxBook are fine, but the getFilesBackoffice call returns a 302 and afterwards triggers the login page. Also the getAllowedFiles afterwards is called fine. It is important to say, that it is always a different Ajax Call and therefore I assume, any Ajax call can cause the problem. A successful Ajax call returns a JSON.
I tried to reconstruct the problem, but it for me it seems to be mission impossible to reconstruct it. I also tried to debug that problem, and tried to check what the error might be... but no chance. Also the php Error Log gives no information.
So next, I downloaded the full "Network Information" from Chrome with "save as HAR with content". Looking at that file, it seems, like the Cookie (with its Session) is deleted.
Here is an excerpt of the HAR with the status 302:
"response": {
"status": 302,
"statusText": "Found",
"httpVersion": "HTTP/1.1",
"headers": [
{
"name": "Date",
"value": "Thu, 20 Dec 2018 09:47:27 GMT"
},
{
"name": "Server",
"value": "Apache/2.4.12 (Unix) OpenSSL/1.0.1p PHP/5.6.11 mod_perl/2.0.8-dev Perl/v5.16.3"
},
{
"name": "X-Powered-By",
"value": "PHP/5.6.11"
},
{
"name": "Content-Type",
"value": "text/html; charset=UTF-8"
},
{
"name": "Location",
"value": "http://localhost/stressfrei/HRMAppMig/Users/login"
},
{
"name": "Connection",
"value": "Keep-Alive"
},
{
"name": "Set-Cookie",
"value": "CAKEPHP=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; Max-Age=0; path=/"
},
{
"name": "Set-Cookie",
"value": "CAKEPHP=2e5gke00430jdkd8ll5jl3ini3; expires=Fri, 21-Dec-2018 09:47:28 GMT; Max-Age=86400; path=/stressfrei/HRMAppMig/; HttpOnly"
},
{
"name": "Set-Cookie",
"value": "CAKEPHP=o3udvthe0rkmjt5djrjvnt3392; expires=Fri, 21-Dec-2018 09:47:28 GMT; Max-Age=86400; path=/stressfrei/HRMAppMig/; HttpOnly"
},
{
"name": "Keep-Alive",
"value": "timeout=5, max=95"
},
{
"name": "Content-Length",
"value": "0"
}
],
"cookies": [
{
"name": "CAKEPHP",
"value": "deleted",
"path": "/",
"expires": "2018-12-20T09:47:27.127Z",
"httpOnly": false,
"secure": false
},
{
"name": "CAKEPHP",
"value": "2e5gke00430jdkd8ll5jl3ini3",
"path": "/stressfrei/HRMAppMig/",
"expires": "2018-12-21T09:47:27.127Z",
"httpOnly": true,
"secure": false
},
{
"name": "CAKEPHP",
"value": "o3udvthe0rkmjt5djrjvnt3392",
"path": "/stressfrei/HRMAppMig/",
"expires": "2018-12-21T09:47:27.127Z",
"httpOnly": true,
"secure": false
}
],
"content": {
"size": 0,
"mimeType": "text/html",
"compression": 0
},
"redirectURL": "http://localhost/stressfrei/HRMAppMig/Users/login",
"headersSize": 717,
"bodySize": 0,
"_transferSize": 717
}
Here is an excerpt of the 200
"response": {
"status": 200,
"statusText": "OK",
"httpVersion": "HTTP/1.1",
"headers": [
{
"name": "Date",
"value": "Thu, 20 Dec 2018 09:52:39 GMT"
},
{
"name": "Server",
"value": "Apache/2.4.12 (Unix) OpenSSL/1.0.1p PHP/5.6.11 mod_perl/2.0.8-dev Perl/v5.16.3"
},
{
"name": "Connection",
"value": "Keep-Alive"
},
{
"name": "X-Powered-By",
"value": "PHP/5.6.11"
},
{
"name": "Content-Length",
"value": "2239"
},
{
"name": "Keep-Alive",
"value": "timeout=5, max=97"
},
{
"name": "Content-Type",
"value": "text/html; charset=UTF-8"
}
],
"cookies": [],
"content": {
"size": 2239,
"mimeType": "text/html",
"compression": 0,
"text": "HERE IS SOME JSON"
},
"redirectURL": "",
"headersSize": 287,
"bodySize": 2239,
"_transferSize": 2526
},
Here is an example of my ajax call.
this.ajaxCall = function(offset) {
var class_prefixTemp = this.class_prefix;
var self = this;
$.ajax({
//ajax options
type: "POST",
url: self.ajaxUrl,
data: {"offset": offset, "elements_per_page": this.elements_per_page, "conditions": this.conditions, "recursive": this.recursive},
dataType: 'json',
//handling return
success: function(result) {
//print out the data from the result
}
});
}
Do you have any idea, how I can find out what my problem is to finally solve it?
Finally the problem was the setting of the Session in the core.php.
In the core.php of CakePhp it is possible to set for the session autoRegenrate to true. This caused the problem that a new session is generated when a new page is loaded. This can cause that long Ajax Requests are working with a wrong session id because it was renewed and therefore the session id didn't fit anymore. This caused a logout.
Finally I had to disable the renewing of the session by setting autoRegenerate to false!
Related
We have created custom APIs in Magento to handle the frontend. We are using Reactjs for the frontend and Axios to hit the APIs.
All the APIs are working fine if we hit from POSTMAN or from the flutter app. We are getting the SID(session-id) from APIs response as same as the SID sent in a request from the previous response.
But in the case of Reactjs and Axios, in each APIs response, the SID(session-id) is different. So, in the case of guest users, we are able to add the products to the cart but are not able to fetch the cart details as SID gets updated.
request:
{
"headers": {
"cache-control": "no-store, no-cache, must-revalidate, post-check=0, pre-check=0",
"content-length": "192",
"content-type": "text/html; charset=UTF-8",
"expires": "Thu, 19 Nov 1981 08:52:00 GMT",
"pragma": "no-cache"
},
"config": {
"transitional": {
"silentJSONParsing": true,
"forcedJSONParsing": true,
"clarifyTimeoutError": false
},
"transformRequest": [
null
],
"transformResponse": [
null
],
"timeout": 330000,
"xsrfCookieName": "XSRF-TOKEN",
"xsrfHeaderName": "X-XSRF-TOKEN",
"maxContentLength": 50000,
"maxBodyLength": -1,
"headers": {
"Accept": "*/*"
},
"withCredentials": false,
"url": "******************************************",
"method": "post",
"baseURL": "",
"params": {
"version": "1.8",
"SID": "bbcosjdf6s4lrd3",
"__store": "default"
},
"responseType": "json",
"maxRedirects": 5,
"data": {},
"meta": {
"requestStartedAt": 1641359394946
}
},
"request": {}
}
I've building out a small app that connects to a Quickbooks API via an SDK. The SDK provides batch operations to help reduce the number of API requests needed.
However, I'm hoping to make a large amount of requests (ie: bulk deletes, uploads in the 100s/1000s). I've gotten the deletes to work, however, now I'm hoping to integrate Laravel's Queue system so that any items in the $batch that fail (due to these business-rules or other reasons) are sent to a worker who will reattempt them after waiting a minute .
Below is an example of a delete request.
class QuickBooksAPIController extends Controller
{
public function batchDelete(Request $request, $category)
{
$chunks = array_chunk($request->data, 30);
foreach ($chunks as $key => $value) {
$batch[$key] = $this->dataService()->CreateNewBatch();
foreach ($value as $id) {
$item = $this->dataService()->FindById($category, $id);
$batch[$key]->AddEntity($item, $id, "delete");
}
$batch[$key]->Execute();
}
return response()->json(['message' => 'Items Deleted'], 200);
}
}
The documentations are a bit sparse for my scenario though. How can I get the failed batch items on order to try again?
Is using batches even the right choice here? Because I have to hit the API anyway to get the $item... which doesn't make sense to me (I think I'm doing something wrong there).
EDIT:
I intentionally sent out a request with more then 30 items and this is the failure message. Which doesn't have the values that didn't make the cut.
EDIT#2:
Ended up using array_chunk to separate the payload into 30 items (which is the limit of the API). Doing so helps process many requests. I've adjusted my code above to represent my current code.
How can I get the failed batch items on order to try again?
If you look at Intuit's documentation, you can see that the HTTP response the API returns contains this information. Here's the example request they show:
{
"BatchItemRequest": [
{
"bId": "bid1",
"Vendor": {
"DisplayName": "Smith Family Store"
},
"operation": "create"
},
{
"bId": "bid2",
"operation": "delete",
"Invoice": {
"SyncToken": "0",
"Id": "129"
}
},
{
"SalesReceipt": {
"PrivateNote": "A private note.",
"SyncToken": "0",
"domain": "QBO",
"Id": "11",
"sparse": true
},
"bId": "bid3",
"operation": "update"
},
{
"Query": "select * from SalesReceipt where TotalAmt > '300.00'",
"bId": "bid4"
}
]
}
And the corresponding response:
{
"BatchItemResponse": [
{
"Fault": {
"type": "ValidationFault",
"Error": [
{
"Message": "Duplicate Name Exists Error",
"code": "6240",
"Detail": "The name supplied already exists. : Another customer, vendor or employee is already using this \nname. Please use a different name.",
"element": ""
}
]
},
"bId": "bid1"
},
{
"Fault": {
"type": "ValidationFault",
"Error": [
{
"Message": "Object Not Found",
"code": "610",
"Detail": "Object Not Found : Something you're trying to use has been made inactive. Check the fields with accounts, customers, items, vendors or employees.",
"element": ""
}
]
},
"bId": "bid2"
},
{
"Fault": {
"type": "ValidationFault",
"Error": [
{
"Message": "Stale Object Error",
"code": "5010",
"Detail": "Stale Object Error : You and root were working on this at the same time. root finished before you did, so your work was not saved.",
"element": ""
}
]
},
"bId": "bid3"
},
{
"bId": "bid4",
"QueryResponse": {
"SalesReceipt": [
{
"TxnDate": "2015-08-25",
"domain": "QBO",
"CurrencyRef": {
"name": "United States Dollar",
"value": "USD"
},
"PrintStatus": "NotSet",
"PaymentRefNum": "10264",
"TotalAmt": 337.5,
"Line": [
{
"Description": "Custom Design",
"DetailType": "SalesItemLineDetail",
"SalesItemLineDetail": {
"TaxCodeRef": {
"value": "NON"
},
"Qty": 4.5,
"UnitPrice": 75,
"ItemRef": {
"name": "Design",
"value": "4"
}
},
"LineNum": 1,
"Amount": 337.5,
"Id": "1"
},
{
"DetailType": "SubTotalLineDetail",
"Amount": 337.5,
"SubTotalLineDetail": {}
}
],
"ApplyTaxAfterDiscount": false,
"DocNumber": "1003",
"PrivateNote": "A private note.",
"sparse": false,
"DepositToAccountRef": {
"name": "Checking",
"value": "35"
},
"CustomerMemo": {
"value": "Thank you for your business and have a great day!"
},
"Balance": 0,
"CustomerRef": {
"name": "Dylan Sollfrank",
"value": "6"
},
"TxnTaxDetail": {
"TotalTax": 0
},
"SyncToken": "1",
"PaymentMethodRef": {
"name": "Check",
"value": "2"
},
"EmailStatus": "NotSet",
"BillAddr": {
"Lat": "INVALID",
"Long": "INVALID",
"Id": "49",
"Line1": "Dylan Sollfrank"
},
"MetaData": {
"CreateTime": "2015-08-27T14:59:48-07:00",
"LastUpdatedTime": "2016-04-15T09:01:10-07:00"
},
"CustomField": [
{
"DefinitionId": "1",
"Type": "StringType",
"Name": "Crew #"
}
],
"Id": "11"
}
],
"startPosition": 1,
"maxResults": 1
}
}
],
"time": "2016-04-15T09:01:18.141-07:00"
}
Notice the separate response object for each request.
The bId value is a unique value you send in the request, which is then echo'd back to you in the response, so you can match up the requests you send with the responses you get back.
Here's the docs:
https://developer.intuit.com/app/developer/qbo/docs/api/accounting/all-entities/batch#sample-batch-request
Is using batches even the right choice here?
Batches make a lot of sense when you are doing a lot of things all at once.
The way you're trying to use them is... weird. What you should probably be doing is:
Batch 1
- go find all your items
Batch 2
- delete all the items
Your existing code doesn't make sense because you're trying to both find the item and delete the item in the exact same batch HTTP request, which isn't possible via the API.
I intentionally sent out a request with more then 30 items and this is the failure message.
No, it's not. That's a PHP error message - you have an error in your code.
You need to fix the PHP error, and then look at the actual response you're getting back from the API.
This is the result I get when I try to validate my API.
Content-Type: application/json
Vary: Accept
{
"valid": false,
"token_uri": "https://mining4btc.com/NFT/rinkeby/CKE/1",
"errors": [
"InvalidTokenUrlResponseException: Invalid response, expected 200 but got 406 for URL: https://mining4btc.com/NFT/rinkeby/CKE/1"
]
}
I'm using this to validate my API:
https://testnets-api.opensea.io/asset/0xe8dD349E3B0F0FA0eE063a2D99541155aFEf14B9/1/validate/
As you can see, it's getting a 406 code.
This is the API:
<?php
header('Content-Type: application/json');
$output = '{
"attributes": [
{
"trait_type": "Eyes",
"value": "cute"
},
{
"trait_type": "Nose",
"value": "cute"
},
{
"trait_type": "Cheeks",
"value": "cute"
},
{
"trait_type": "Toes",
"value": "cute"
},
{
"trait_type": "Ability",
"value": "chairs"
},
{
"display_type": "boost_number",
"trait_type": "Cuteness",
"value": 5000
},
{
"display_type": "number",
"trait_type": "Age",
"value": 1
}
],
"description": "Thinking about my Mommy.",
"external_url": "https://mining4btc.com/NFT/rinkeby/CKE/external",
"image": "https://mining4btc.com/NFT/rinkeby/CKE/proof/1.jpg",
"name": "Chillin"
}';
$decoded = json_decode($output);
echo json_encode($decoded);
?>
This is a contract API for a NFT following the OpenSea documents; deployed with Truffle to rinkeby.
I have confirmed that this is because Bluehost actively blocks (by returning this code) requests with Accept:application/json headers. You have to contact Bluehost and ask them to whitelist the IP addresses that you want to be able to access the metadata.
As far as I can tell, they do this because they want to push people to pay for a VPS, because they are assuming this kind of request would go to some kind of robust API that requires significant backend processing.
Im trying to send a email template along with a URL whose click count should be tracked using SparkPost APIs?
Example: if I give www.google.com its has to change to
http://go.sparkpostmail1.com/f/a/EgvUoS2LdGPzMx-AURKwZA~~/AABUGAA~/RgRZK0BSP0EIAGukLuGW3OxXA3NwY1gEAAAAAFkGc2hhcmVkQgoAAVK7SFdpNVEbUhFuaWNvbGFzQGR1cmFuZC5jaAlRBAAAAABEUWh0dHBzOi8vZGlzaGx5Lm1lbnUvZC9XYXNoaW5ndG9uL1JlZ2VudF9UaGFpL0Jhc2lsX0phZS81NjBmMzk5MmQ0YWUxNTAzMDBmZWZmMGIiLEcCe30.
POST /api/v1/transmissions?num_rcpt_errors=3
{
"options": {
"start_time": "now",
"open_tracking": true,
"click_tracking": true,
"transactional": false,
"sandbox": false,
"ip_pool": "sp_shared",
"inline_css": false
},
"description": "Christmas Campaign Email",
"campaign_id": "christmas_campaign",
"metadata": {
"user_type": "students",
"education_level": "college"
},
"substitution_data": {
"sender": "Big Store Team",
"holiday_name": "Christmas"
},
"recipients": [
{
"address": {
"email": "wilma#flintstone.com",
"name": "Wilma Flintstone"
},
"tags": [
"greeting",
"prehistoric",
"fred",
"flintstone"
],
"metadata": {
"age": "24",
"place": "Bedrock"
},
"substitution_data": {
"customer_type": "Platinum",
"year": "Freshman"
}
}
],
"content": {
"from": {
"name": "Fred Flintstone",
"email": "fred#flintstone.com"
},
"subject": "Big Christmas savings!",
"reply_to": "Christmas Sales <sales#flintstone.com>",
"headers": {
"X-Customer-Campaign-ID": "christmas_campaign"
},
"text": "Hi \nSave big this Christmas in your area ! \nClick http://www.example.com and get huge discount\n Hurry, this offer is only to \n ",
"html": "<p>Hi \nSave big this Christmas in your area ! \nClick http://www.example.com and get huge discount\n</p><p>Hurry, this offer is only to \n</p><p></p>"
}
}
To enable "click tracking", set options.click_tracking=true field in your request. You have already done this but it looks like your links in the content.html are not HTML anchors (<a> tags) but just plain text links.
SparkPost will only track HTML anchors so I suggest changing this:
http://www.example.com
to this:
www.example.com
I have the following json, I'm sending through AJAX, but in the server side the json_decode returning an empty array. I'm sending different values as well, and in that case it's working fine. I check int this link, and this is a valid JSON.
[
{
"name": "bettype",
"value": "All"
},
{
"name": "bookies",
"value": "Interwetten"
},
{
"name": "sporttype",
"value": "Soccer"
},
{
"name": "team1",
"value": "Braunschweig"
},
{
"name": "team2",
"value": "Bayern Munich"
},
{
"name": "league",
"value": "Germany DFB Cup (90`)"
}
]
UPDATED:
this is the server side code:
var_dump((stripslashes($_GET['data']));
var_dump(json_decode(stripslashes($_GET['data'])));
and this is the output:
string(244) "[{"name":"bettype","value":"All"},{"name":"bookies","value":"Interwetten"},{"name":"sporttype","value":"Soccer"},{"name":"team1","value":"Braunschweig"},{"name":"team2","value":"Bayern Munich"},{"name":"league","value":"Germany DFB Cup (90�)"}]" NULL
It works fine for me.
http://sandbox.phpcode.eu/g/80941.php
Check your browser configuration/charset and try again