I want to backup all Facebook photos from a user with a webapp made in PHP/Laravel. What I do right now is:
I first get all albums with /me/albums
Then I get all photos from each album with /<album id>/photos
And then I retrieve each photo with /<photo id>/picture?type=normal
And that gets me this:
Facebook\FacebookResponse::__set_state(array(
'httpStatusCode' => 302,
'headers' =>
array (
'x-app-usage' => '{"call_count":0,"total_cputime":0,"total_time":0}',
'location' => 'https://scontent.fros6-1.fna.fbcdn.net/v/t31.0-8/s720x720/241688_10150189954577077_6076941_o.jpg?_nc_cat=106&ccb=2&_nc_sid=e007fa&_nc_ohc=6BG0bnvmDO0AX-ayiLu&_nc_ht=scontent.fros6-1.fna&tp=7&oh=2eb322e48d2bcba4c4f06b95d8803922&oe=5FE0AF19',
'expires' => 'Sat, 01 Jan 2000 00:00:00 GMT',
'x-fb-request-id' => 'AV2g1mnIDjWDzIgHyD48oNx',
'strict-transport-security' => 'max-age=15552000; preload',
'x-fb-trace-id' => 'E5eCApEMOPW',
'facebook-api-version' => 'v9.0',
'content-type' => 'image/jpeg',
'x-fb-rev' => '1003022644',
'cache-control' => 'private, no-cache, no-store, must-revalidate',
'vary' => 'Accept-Encoding',
'pragma' => 'no-cache',
'access-control-allow-origin' => '*',
'x-fb-debug' => '9brMqjQf3QpZ95/RjANHrhZvYY30VzEivA91+bsysa+SwAib5U6gZl5jlqjOscOusDviJe0wjoCuIJoyc67bbQ==',
'content-length' => '0',
'date' => 'Sun, 22 Nov 2020 17:22:05 GMT',
'alt-svc' => 'h3-29=":443"; ma=3600,h3-27=":443"; ma=3600',
),
'body' => '',
'decodedBody' =>
array (
),
'request' =>
Facebook\FacebookRequest::__set_state(array(
'app' =>
Facebook\FacebookApp::__set_state(array(
'id' => '<hidden>',
'secret' => '<hidden>',
)),
'accessToken' => <hidden>,
'method' => 'GET',
'endpoint' => '/10150189954577077/picture?type=normal',
'headers' =>
array (
'Content-Type' => 'application/x-www-form-urlencoded',
),
'params' =>
array (
),
'files' =>
array (
),
'eTag' => NULL,
'graphVersion' => 'v9.0',
)),
'thrownException' => NULL,
))
So what I need from there is the location. I store that object in $response. But I can't do $response['headers'] because it says is not an array (using json_encode gives and empty array) and also can't do $response->headers or $response->headers() because it says it's protected.
Who do I access image location within that Facebook Response?
The PHP SDK apparently does not have a dedicated section in the FB docs any more, they are redirecting directly to GitHub.
If you check the /docs/reference folder there and look for the class in question, you can find the available public methods listed there though.
https://github.com/facebookarchive/php-graph-sdk/blob/master/docs/reference/FacebookResponse.md
getHeaders()
public array getHeaders()
Returns the response headers that were returned.
Related
I am using queue for the first time in Laravel.
I can't seem to get it work. I am sending an email and also calling a url with curl ().
I have even tried file_content_get(), yet it doesn't seem to work. The email seems to work just fine...
My question is: is there a different approach to calling an endpoint using Queue?
public function handle()
{
$email = new Airtime();
$ch = curl_init("some-url");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// exec($ch);
curl_exec($ch);
Mail::to($this->details['email'])->send($email);
}
The email gets sent, but the curl is completely ignored.
Unless the function is disabled in php.ini in disable_functions directive or something blocks your requests on the network level, there is no specific reason this should not be executed. Are you sure that the endpoint being called did not in fact receive the request?
Calling remote endpoints from queues works fine for me. I just tested it now with a snippet below:
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
$result = \Http::get('https://api.publicapis.org/entries')->json('entries');
\Log::info($result);
}
Result:
[2022-10-01 11:12:25] local.INFO: array (
0 =>
array (
'API' => 'AdoptAPet',
'Description' => 'Resource to help get pets adopted',
'Auth' => 'apiKey',
'HTTPS' => true,
'Cors' => 'yes',
'Link' => 'https://www.adoptapet.com/public/apis/pet_list.html',
'Category' => 'Animals',
),
1 =>
array (
'API' => 'Axolotl',
'Description' => 'Collection of axolotl pictures and facts',
'Auth' => '',
'HTTPS' => true,
'Cors' => 'no',
'Link' => 'https://theaxolotlapi.netlify.app/',
'Category' => 'Animals',
),
2 =>
array (
'API' => 'Cat Facts',
'Description' => 'Daily cat facts',
'Auth' => '',
'HTTPS' => true,
'Cors' => 'no',
'Link' => 'https://alexwohlbruck.github.io/cat-facts/',
'Category' => 'Animals',
),
3 =>
array (
'API' => 'Cataas',
'Description' => 'Cat as a service (cats pictures and gifs)',
'Auth' => '',
'HTTPS' => true,
'Cors' => 'no',
'Link' => 'https://cataas.com/',
'Category' => 'Animals',
)
Im creating a simple integration that should post our WooCommerce orders over to the Deep Data seciton via the API (V3)
Here is a simple example of the request Im trying to make.
Im running this script manually for the time being just to get it working. This is the array Im sending as my request using wp_remote_post($url, $request)
Array
(
[key] => KEY
[url] => URL/ecomOrders
[settings] => Array
(
[method] => POST
[timeout] => 5
[redirection] => 5
[httpversion] => 1.0
[user-agent] => WordPress/5.2.1; https://www.XXXX.com
[blocking] => 1
[body] => {"ecomOrder":{JSONORDER}}
[headers] => Array
(
[Api-Token] => KEY
)
)
)
This is (part of) what I get back from my response.
[body] =>
[response] => Array
(
[code] => 403
[message] => Forbidden
)
I have double checked the API key and URL and just a side note, we are already using the same method and script details in a similar reques to add contacts which is working fine.
Here is the code Im using (all $var's are defined earlier in the script):
$request = array(
'key' => $key,
'url' => $url,
'settings' => array(
'method' => 'POST',
'sslverify' => false,
'timeout' => 5,
'redirection' => 0,
'httpversion' => '1.0',
'user-agent' => 'WordPress/' . $wp_version . '; ' . home_url(),
'blocking' => true,
'body' => $body,
'headers' => array(
'Api-Token' => $key,
)
)
);
$response = wp_remote_post($url, $request);
We just ran into a similar issue today; where all the headers and payload were set correctly, but the API was returning a 401.
Our payload needed to be sent as json and we had to explicitly define that in the headers. Like so:
'content-type' => 'application/json'
Also, it look likes the request/args array isn't structured how WordPress recommends in the codex. (arguements)
$key = 'myKey';
$url = 'myURL'
$body = array('ecomOrder' => $myOrder);
$request = array(
'method' => 'POST',
'sslverify' => false,
'timeout' => 5,
'redirection' => 0,
'httpversion' => '1.0',
'user-agent' => 'WordPress/' . $wp_version . '; ' . home_url(),
'blocking' => true,
'body' => json_encode($body),
'headers' => array(
'content-type' => 'application/json',
'Api-Token' => $key,
)
);
$response = wp_remote_post($url, $request);
This may be a shot in the dark as I'm not familiar with Active Campaign's API, but hopefully it helps.
Resources
This stackoverflow article really helped.
In my ReportController.php, my function receives Request $request, as below:
class ReportController extends Controller{
public function store(Request $request)
{
\Log::info("Request content:");
\Log::info($request);
error_log("request:");
error_log($request);
$insertID = Report::create([
'action' => $request->action,
'reportID' => $request->reportID,
'incidentDate' => $request->incidentDate,
'who' => $request->who,
'location' => $request->location,
'description' => $request->details,
'submittedByName' => $request->submittedByName,
'submittedByMobile' => $request->submittedByMobile,
'submittedByEmail' => $request->submittedByEmail,
'attachments' => $attachments,
'attachmentCount' => $attachmentCount,
'request' => $request
])->id;
}
}
Strangely enough, the value of $request changes depending on where I dump/store them. For example, in my log file where I log using \Log::info($request), it displays something like:
[2019-05-28 17:35:27] local.INFO: array (
'action' => 'TellUsMore',
'reportID' => 'b19xr211gcbvc',
'incidentDate' => '2019-05-29',
'location' => 'ggg',
'description' => 'gg',
'suggestion' => 'sdfsdf',
'files' =>
array (
0 =>
Illuminate\Http\UploadedFile::__set_state(array(
'test' => false,
'originalName' => 'reports (1).xlsx',
'mimeType' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'error' => 0,
'hashName' => NULL,
)),
1 =>
Illuminate\Http\UploadedFile::__set_state(array(
'test' => false,
'originalName' => 'love your parents - we\'re so busy growing up, we often forget that they\'re growing old.jpg',
'mimeType' => 'image/jpeg',
'error' => 0,
'hashName' => NULL,
)),
),
)
but in my error_log($request) which dumps the value in console, it displays
[Wed May 29 01:35:27 2019] POST /api/report/store HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Cache-Control: no-cache
Connection: keep-alive
Content-Length: 25172
Content-Type: multipart/form-data; boundary=--------------------------416520203821764707296428
Host: localhost:8000
Postman-Token: 76adb08d-631e-4f10-9a5f-60bc8d015aed
User-Agent: PostmanRuntime/7.6.0
It's the same when I stored the $request value inside database. I meant to store the $request value that's being displayed as in my laravel log file, but instead it saved the value of $request as what's being displayed in my console.
What did I miss here?
error_log() calls $request->__toString(), your Log class calls var_export() for some reason. That's the difference ;)
I want to download a pdf file with guzzle. Is this possible?
I tried this code:
$response = $this->client->post(self::API_BASE_URL.self::API_LABEL_URL,
[
'future' => true,
'json' => [$this->json],
'headers' => ['Content-Type' => 'application/json', 'Accept' => 'application/pdf'],
'query' => [
'return-type' => 'pdf',
'x-api-key' => $this->apiKey
],
]);
and I get
[body] => GuzzleHttp\Stream\Stream Object(
[stream:GuzzleHttp\Stream\Stream:private] => Resource id #120
[size:GuzzleHttp\Stream\Stream:private] => 649
[seekable:GuzzleHttp\Stream\Stream:private] => 1
[readable:GuzzleHttp\Stream\Stream:private] => 1
[writable:GuzzleHttp\Stream\Stream:private] => 1
[uri:GuzzleHttp\Stream\Stream:private] => php://temp
[customMetadata:GuzzleHttp\Stream\Stream:private] => Array
But I don't have an idea how I can handle this Resource id to save the pdf file.
I use guzzle 5.3 and PHP 5.4 with no options to update the php version.
You can use Guzzle sink option to download file - http://docs.guzzlephp.org/en/stable/request-options.html#sink
$pdfFilePath = __DIR__ . '/resource/file.pdf'; // specify your path
$pdfFileResource = fopen($pdfFilePath, 'w+');
$this->client->post(
self::API_BASE_URL . self::API_LABEL_URL,
[
'future' => true,
'json' => [$this->json],
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/pdf'
],
'query' => [
'return-type' => 'pdf',
'x-api-key' => $this->apiKey
],
'sink' => $pdfFileResource
]
);
More examples - https://github.com/andriichuk/php-curl-cookbook#download-file
When add a new app to access saml, I am facing this issue.
SSOService.php:1 GET https://saml.testing.net/www/saml2/idp/SSOService.php?spentityid=newapp&cookieTime=1459920375
net::ERR_TOO_MANY_REDIRECTS
in my local I don't facing any issue, but when I copy the codes to staging servers, then it shows ERR_TOO_MANY_REDIRECTS errors, keep redirecting, and not able to display the saml login page. The Staging servers with Load balancers, would this caused the error?
Thanks.
Update:
$config = array(
'baseurlpath' => 'https://saml.testing.net/',
'certdir' => '/etc/test/sslcerts/',
'tempdir' => '/tmp',
'datadir' => 'data/',
'auth.adminpassword' => '1234567',
'admin.protectindexpage' => TRUE,
'admin.protectmetadata' => TRUE,
'secretsalt' => 'xxxxxxxxx',
'timezone' => NULL,
// logging related options
'loggingdir' => '/var/log/simplesamlphp/',
'logging.level' => LOG_WARNING,
'logging.logfile' => 'simplesaml_' .date("Ymd") . '.log',
'debug' => true,
'showerrors' => true,
'logging.handler' => 'file',
'logging.facility' => LOG_USER,
'logging.processname' => 'simplesaml',
'debug.validatexml' => FALSE,
'enable.saml20-idp' => TRUE,
'enable.shib13-idp' => FALSE,
'enable.adfs-idp' => FALSE,
'enable.wsfed-sp' => FALSE,
'enable.authmemcookie' => TRUE,
'session.duration' => 2*(60*60),
'session.requestcache' => 4*(60*60),
'session.cookie.lifetime' => 0,
'session.cookie.path' => '/',
'session.phpsession.cookiename' => 'SimpleSAMLSessionID',
'session.cookie.name' => 'SimpleSAMLSessionID',
'session.cookie.domain' => NULL,
'session.cookie.secure' => FALSE,
'session.cookie.lifetime' => 0,
'session.datastore.timeout' => 4*(60*60),
'session.state.timeout' => (60*60),
'session.phpsession.savepath' => NULL,
'session.phpsession.httponly' => FALSE,
'session.disable_fallback' => FALSE,
'session.authtoken.cookiename' => 'SimpleSAMLAuthToken',
'session.rememberme.enable' => FALSE,
'session.rememberme.checked' => FALSE,
'session.rememberme.lifetime' => 1209600, // 14 days
'enable.http_post' => FALSE,
'language.available' => array('en'),
'language.default' => 'en',
'attributes.extradictionary' => NULL,
'theme.use' => 'oldtheme:abcdef',
'attributes.extradictionary' => NULL,
'default-wsfed-idp' => 'urn:federation:pingfederate:localhost',
'idpdisco.enableremember' => TRUE,
'idpdisco.rememberchecked' => TRUE,
'idpdisco.validate' => TRUE,
'idpdisco.extDiscoveryStorage' => NULL,
'idpdisco.layout' => 'dropdown',
'shib13.signresponse' => TRUE,
'authproc.idp' => array(
10 => "frogauth:LogHandler",
30 => 'core:LanguageAdaptor',
45 => array('class' => 'core:StatisticsWithAttribute', 'attributename' => 'realm', 'type' => 'saml20-idp-SSO'),
50 => 'core:AttributeLimit',
99 => 'core:LanguageAdaptor',
100 => "newauth:ToLogin",
101 => "newauth:VerifyLogin",
99 => 'core:LanguageAdaptor',
),
'authproc.sp' => array(
99 => 'core:LanguageAdaptor',
),
'metadata.sources' => array(
array('type' => 'flatfile'),
),
'store.type' => 'memcache',
'memcache_store.servers' => array(
array(
array('hostname' => '10.11.11.11'),
),
),
'memcache_store.expires' => 36 * (60*60),
'metadata.sign.enable' => FALSE,
'metadata.sign.privatekey' => NULL,
'metadata.sign.privatekey_pass' => NULL,
'metadata.sign.certificate' => NULL,
'proxy' => null,
'xframe_options'=> array( 'enable' => TRUE, 'trusted_sites' => array()),
'session.duration' => 2*(60*60),
'theme.use' => "newtheme:multitheme",
);
saml20-sp-remote.php
$metadata['newapp'] = array(
'AssertionConsumerService' => 'https://www.newapp.com/mobile/saml',
'SingleLogoutService' => 'https://www.newapp.com/mobile/logout',
'Theme' => 'mobile',
);
In my case the SameSite=None cookie attribute was the culprit. SameSite=None cookies must be used along with the secure attribute!
Solution:
'session.cookie.secure' => true // config.php
If your service is running behind a reverse proxy and is not running over https you additionally need to define the URL schema:
'baseurlpath' => 'https://my.url.com/<path_to_simple_saml>' // indicating the https schema (config.php)
If it helps at all, whenever this occurs in our setup it is because something has gone wrong with the cookies.
The user is not being seen as logged in at the service because the cookies aren't set correctly. Therefore they are redirected to the idp at which point they are shown as logged in and redirected back to the service; and repeat.
Basically your service thinks they aren't logged in, saml thinks they are; and they both keep passing the buck!
I've just run into a similar redirect issue. SimpleSAMLPHP would load fine but when trying to login as an admin it would go into an infinite loop loading the loginuserpass.php and as_login.php pages (redirected initially from /module.php/core/login-admin.php?ReturnTo=XXX).
After a lot of debugging I found that the problem was actually Varnish caching which was stopping the session state from being loaded. This happened no matter what session storage was selected (phpsession, memcache or sql).
Disabling varnish caching on the SimpleSAMLPHP paths fixed the issue for me.
Hope this helps anyone else with this issue.
And here is still another possible solution to try (worked for me after searching for hours, and after correcting the 'session.phpsession.savepath'): Go into the Firefox developer tools (or the browser of your choice) and in the "web storage" remove all cookies.
Close the connection when the page content ends.
In my case the culprit was a git/merge error in the session.phpsession.savepath ... fixing it solved the redirect issue
'session.phpsession.savepath' => "/path/to"