Sonata Media CDN Rackspace - symfony

I have the next problem with Sonata Media:
I'm trying to use the Rackspace CDN for uploading images:
My config file looks like this based on current documentation:
cdn:
server:
path: %cdn_url%
filesystem:
local:
directory: %kernel.root_dir%/../web/uploads/media
create: false
rackspace:
url: %rackspace.opencloud.host%
secret:
username: %rackspace.opencloud.username%
apiKey: %rackspace.opencloud.api_key%
region: LON
containerName: projectName
create_container: false
replicate:
master: sonata.media.adapter.filesystem.opencloud
slave: sonata.media.adapter.filesystem.local
And on providers config:
providers:
image:
filesystem: sonata.media.filesystem.replicate
cdn: sonata.media.cdn.server
resizer: sonata.media.resizer.square
allowed_extensions: ['jpg', 'png', 'gif', 'jpeg']
allowed_mime_types: ['image/pjpeg','image/jpeg','image/png','image/x-png', 'image/gif']
The problem is(how I discovered this bug)if Rackspace is down or incorrect username/password are provided on every page of the app I'm getting this answer:
Client error response [status code] 401 [reason phrase] Unauthorized [url] https://lon.auth.api.rackspacecloud.com/v2.0/tokens
This is because Gaufrette Opencloud tries to create a connection on Kernel load.
The quickest solution as a temporary fix was to create a compiler pass and check if the authenticate method returns false then replace argument 0 for replicate definition with the local filesystem adaptor.
My questions are:
How can I avoid creating the Rackspace connection on Kernel Load?
In case Rackspace is down how can I swap between Rackspace or other adapter(local or other ftp server)
Thank you in advance and please in case there are not sufficient information provided please leave a comment.

Apparently there is a solution for lazy loading implemented in Gaufrette: https://github.com/KnpLabs/KnpGaufretteBundle/issues/72
All I had to do is:
sonata.media.adapter.open_stack:
class: OpenCloud\Rackspace
arguments: [ %rackspace.opencloud.host%, { username: %rackspace.opencloud.username%, apiKey: %rackspace.opencloud.api_key% }]
sonata.media.adapter.object_store_factory:
class: Gaufrette\Adapter\OpenStackCloudFiles\ObjectStoreFactory
arguments: [ #sonata.media.adapter.open_stack, "LON", ""]
sonata.media.adapter.filesystem.lazyopencloud:
class: Gaufrette\Adapter\LazyOpenCloud
arguments: [ #sonata.media.adapter.object_store_factory, %rackspace.opencloud.container_name%]
And change replicate master to sonata.media.adapter.filesystem.lazyopencloud
Hope it helps :)

Related

Error with Gatsby plugin Gatsby-Source-Wordpress

I'm trying to setup my first gatsby + wordpress site. I'm following this tutorial.
I get the site running but at the point where I should get the data from WP I get stuck. I added Gatsby-Source-Wordpress plugin. After I restarted site it throws this error:
success open and validate gatsby-configs - 0.102 s
success load plugins - 0.631 s
success onPreInit - 0.019 s
success initialize cache - 0.053 s
success copy gatsby files - 0.161 s
success onPreBootstrap - 0.040 s
info Creating GraphQL type definition for File
Path: /wp-json
The server response was "404 Not Found"
ERROR #11321 PLUGIN
"gatsby-source-wordpress" threw an error while running the sourceNodes lifecycle:
Cannot read property 'data' of undefined
TypeError: Cannot read property 'data' of undefined
- fetch.js:141 fetch
[gatsby-wordpress]/[gatsby-source-wordpress]/fetch.js:141:21
- next_tick.js:68 process._tickCallback
internal/process/next_tick.js:68:7
warn The gatsby-source-wordpress plugin has generated no Gatsby nodes. Do you need it?
success source and transform nodes - 0.327 s
success building schema - 0.404 s
success createPages - 0.019 s
success createPagesStatefully - 0.090 s
success onPreExtractQueries - 0.022 s
success update schema - 0.079 s
success extract queries from components - 0.595 s
success write out requires - 0.103 s
success write out redirect data - 0.032 s
success Build manifest and related icons - 0.263 s
success onPostBootstrap - 0.308 s
⠀
info bootstrap finished - 6.617 s
⠀
success run static queries - 0.105 s — 3/3 36.11 queries/second
success run page queries - 0.044 s — 5/5 230.97 queries/second
DONE Compiled successfully in 4851ms 10:46:42 AM
⠀
You can now view gatsby-starter-default in the browser.
⠀
http://localhost:8000/
⠀
View GraphiQL, an in-browser IDE, to explore your site's data and schema
⠀
http://localhost:8000/___graphql
⠀
Note that the development build is not optimized.
To create a production build, use npm run build
⠀
ℹ 「wdm」:
ℹ 「wdm」: Compiled successfully.
I run WP locally with Mamp and I'm able to see JSON data here: http://localhost:8888/GatsbyWP/wp-json/ .
Here's my gatsby-config.js file:
module.exports = {
siteMetadata: {
title: `Gatsby wordpress test`,
description: `Testing...`,
author: `#gatsbyjs`,
},
plugins: [
`gatsby-plugin-react-helmet`,
{
resolve: `gatsby-source-filesystem`,
options: {
name: `images`,
path: `${__dirname}/src/images`,
},
},
`gatsby-transformer-sharp`,
`gatsby-plugin-sharp`,
{
resolve: `gatsby-plugin-manifest`,
options: {
name: `gatsby-starter-default`,
short_name: `starter`,
start_url: `/`,
background_color: `#663399`,
theme_color: `#663399`,
display: `minimal-ui`,
icon: `src/images/gatsby-icon.png`,
},
},
{
resolve: "gatsby-source-wordpress",
options: {
baseUrl: `localhost:8888`,
protocol: `http`,
hostingWPCOM: false,
useACF: true,
},
},
`gatsby-plugin-sitemap`,
],
}
I'm stuck and don't have any clue what to do now. I found that other people had similar issue than this but didn't find any good answers or direction where to try figure out my problem.
Thanks in advance!
The options of gatsby-source-wordpress require...
the base URL of the Wordpress site without the trailing slash and the protocol. This is required.
Example : 'gatsbyjsexamplewordpress.wordpress.com' or 'www.example-site.com'
module.exports = {
siteMetadata: {
title: `Gatsby wordpress test`,
description: `Testing...`,
author: `#gatsbyjs`,
},
plugins: [
{
resolve: "gatsby-source-wordpress",
options: {
baseUrl: `localhost:8888/GatsbyWP`,
protocol: `http`,
hostingWPCOM: false,
useACF: true,
},
},
],
}
When Sourcing on hosting from Services Like Godaddy The axios/node clients can be dubious about them and reject the https crt, I have seen this rectified in two ways
1) With adding a third party go daddy crt bundle for example https://ssl-ccp.godaddy.com/repository?origin=CALLISTO, if you have your own server that's fine. So adding this to axios:
var agent = new https.Agent({
ca: fs.readFileSync('ca.pem')
});
axios.get(url, { agent: agent });
// or
var instance = axios.create({ agent: agent });
instance.get(url);
or node
export NODE_EXTRA_CA_CERTS=[your CA certificate file path]
2) But what if you are on Netlify or hosting through gitlab or other, What worked for me was changed my gatsby config protocol to http, this allowed me to source from my site just fine and provided all assets are https anyway, even when I deployed to my https site it all still worked. This stumped me for days, hope this helps someone
{
resolve: `gatsby-source-wordpress`,
options: {
/*
* The base URL of the WordPress site without the trailingslash and the protocol. This is required.
* Example : 'dev-gatbsyjswp.pantheonsite.io' or 'www.example-site.com'
*/
baseUrl: `example.com`,
// The protocol. This can be http or https.
protocol: `http`,
// Indicates whether the site is hosted on wordpress.com.
// If false, then the assumption is made that the site is self hosted.
// If true, then the plugin will source its content on wordpress.com using the JSON REST API V2.
// If your site is hosted on wordpress.org, then set this to false.
hostingWPCOM: false,
Hey you need to make sure you query the post types you pull in and you also need to make sure theres data there to be consumed but here's what you config should look like.
{
resolve: `gatsby-source-wordpress`,
options: {
baseUrl: process.env.API_URL,
protocol: process.env.API_PROTOCOL,
hostingWPCOM: false,
useACF: true,
includedRoutes: [
"**/categories",
"**/posts",
"**/pages",
"**/media",
"**/tags",
"**/taxonomies",
"**/users",
"**/menus",
"**/portfolio",
"**/services",
"**/qualifications",
"**/gallery",
"**/logo",
"**/location",
],
},
},
This may be of help to someone in case all the recommended solutions above do not solve your problems.
It may be that you are using the later version of gatsby and so little changes were made to the way gatsby-source-wordpress plugin works
https://www.gatsbyjs.com/docs/how-to/sourcing-data/sourcing-from-wordpress/
this site was helpful. Check it out too.

Symfony 4 enable logging with Monolog's Redis handler

I have a working ELK stack connected to Redis.
I also have a working stateless Symfony 4 application and I want to send all the production logs to my Redis.
I know Monolog has a Redis handler, but I don't know how I'm supposed to tweak the config/prod/monolog.yaml file to accomplish this of if there’s another approach.
This is how it looks right now:
monolog:
handlers:
main:
type: fingers_crossed
action_level: error
handler: nested
excluded_http_codes: [404]
nested:
type: stream
path: "php://stderr"
level: debug
console:
type: console
process_psr_3_messages: false
channels: ["!event", "!doctrine"]
deprecation:
type: stream
path: "php://stderr"
deprecation_filter:
type: filter
handler: deprecation
max_level: info
channels: ["php"]
The approach I took was, first installing the predis client:
composer require predis/predis
Then create a custom service class that extends the RedisHandler class that comes with the Monolog package:
namespace App\Service\Monolog\Handler;
use Monolog\Handler\RedisHandler;
use Monolog\Logger;
use Predis\Client as PredisClient;
class Redis extends RedisHandler
{
public function __construct( $host, $port = 6379, $level = Logger::DEBUG, $bubble = true, $capSize = false)
{
$predis = new PredisClient( "tcp://$host:$port" );
$key = 'logstash';
parent::__construct($predis, $key, $level, $bubble, $capSize);
}
}
Next, activate the service we just created on the services.yml config file:
services:
monolog.handler.redis:
class: App\Service\Monolog\Handler\Redis
arguments: [ '%redis.host%' ]
Be sure the parameter redis.host is set and points to your Redis server. In my case, my parameter value is the IP of my Redis server.
I added other parameters to the class like port and log level. You can set it at the moment of instantiating your service like with the host parameter.
Finally, configure your custom log handler service in your monolog.yaml config file. In my case, I need it only the production logs with the config as follow:
handlers:
custom:
type: service
id: monolog.handler.redis
level: debug
channels: ['!event']

Configuring LiipImagineBundle Symfony to work with Flysystem

I've been trying to configure a CDN (S3) to work with LiipImagineBundle, but keep getting stuck when it is asking for a non-existent service.
What does this mean?
The value of the filesystem_service property must be a service that returns an instance of League\Flysystem\Filesystem.
From here: http://symfony.com/doc/current/bundles/LiipImagineBundle/cache-resolver/flysystem.html
and here: http://symfony.com/doc/current/bundles/LiipImagineBundle/data-loader/flysystem.html
I have tried to create a service that returns an instance of League\Flysystem\Filesystem as follows:
league.flysystem.s3adaptor:
class: League\Flysystem\AwsS3v3\AwsS3Adapter
arguments: ['#acme.s3_client', '%amazon.s3.bucket%', 's3_fs', '#?']
league.flysystem.filesystem:
class: League\Flysystem\Filesystem
arguments: ['#league.flysystem.s3adaptor', '#?']
calls:
- [addPlugin, ['#oneup_flysystem.plugin.list_with']]
I'm not sure if this is along the right lines or not, but I can't get this working.
Any help or advice will be greatly appreciated.
I was on the right lines, I had just misconfigured my LiipImagineBundle slightly.
To return an instance of League\Flysystem\Filesystem you first need to create a service for the adaptor that you want to use, in this case league.flysystem.s3adaptor does this. Then pass that as an argument to league.flysystem.filesystem.
league.flysystem.s3adaptor:
class: League\Flysystem\AwsS3v3\AwsS3Adapter
arguments: ['#acme.s3_client', '%amazon.s3.bucket%']
league.flysystem.filesystem:
class: League\Flysystem\Filesystem
arguments: ['#league.flysystem.s3adaptor']
calls:
- [addPlugin, ['#oneup_flysystem.plugin.list_with']]
LiipImagineBundle config:
liip_imagine:
resolvers:
profile_photos:
flysystem:
filesystem_service: league.flysystem.filesystem
root_url: "https://s3.eu-west-2.amazonaws.com/nameofthebucket/"
cache_prefix: media/cache
visibility: public
loaders:
profile_photos:
flysystem:
filesystem_service: league.flysystem.filesystem
data_loader: profile_photos
cache: profile_photos

Having problems setting up AWS S3/Cloudfront with Symfony and LiipImagineBundle

I'm trying to set up AWS S3/Cloudfront to work with liipimaginebundle in Symfony, but I really have no idea what I'm doing.
So far I have tried the following documented here http://symfony.com/doc/current/bundles/LiipImagineBundle/cache-resolver/aws_s3.html:
Installed aws-sdk-php:
"require": {
"aws/aws-sdk-php": "^3.28",
}
Set up my parameters (with the correct values not this dummy data):
amazon.s3.key: "your-aws-key"
amazon.s3.secret: "your-aws-secret"
amazon.s3.bucket: "your-bucket.example.com"
amazon.s3.region: "your-bucket-region"
Set up a resolver (although I'm not sure what that even means).
"%amazon.s3.cache_bucket%" is in the documentation but the parameter doesn't exist so I used "%amazon.s3.bucket%" instead:
liip_imagine:
cache: profile_photos
resolvers:
profile_photos:
aws_s3:
client_config:
credentials:
key: "%amazon.s3.key%"
secret: "%amazon.s3.secret%"
region: "%amazon.s3.region%"
bucket: "%amazon.s3.bucket%"
get_options:
Scheme: https
put_options:
CacheControl: "max-age=86400"
Added these lines to create the services:
services:
acme.amazon_s3:
class: Aws\S3\S3Client
factory: Aws\S3\S3Client
arguments:
-
credentials: { key: "%amazon.s3.key%", secret: "%amazon.s3.secret%" }
region: "%amazon.s3.region%"
acme.imagine.cache.resolver.amazon_s3:
class: Liip\ImagineBundle\Imagine\Cache\Resolver\AwsS3Resolver
arguments:
- "#acme.amazon_s3"
- "%amazon.s3.bucket%"
tags:
- { name: "liip_imagine.cache.resolver", resolver: "amazon_s3" }
I'm currently getting this error when I run php bin/console server:run:
PHP Fatal error: Uncaught Symfony\Component\Debug\Exception\UndefinedFunctionException: Attempted to call function "S3Client" from namespace "Aws\S3". in /var/www/swing-polls/var/cache/dev/appDevDebugProjectContainer.php:360
I've tried half a dozen other configs/tutorials to no avail. If someone can point me in the right direction I'd be incredibly grateful.
Using the code provided at Simple S3 Symfony Service with a few tweaks, I've been able to get my images to upload to my s3 bucket, but I just don't know how to get liipimaginebundle work with them.
In vendor/liip/imagine-bundle/DependencyInjection/Compiler/ResolversCompilerPass.php you can see the CompilerPass is getting the value from "resolver" attribute of the tag and is using it to create a Reference object. This means the resolver should contain the id of a service.
Try replacing
tags:
- { name: "liip_imagine.cache.resolver", resolver: "amazon_s3" }
with
tags:
- { name: "liip_imagine.cache.resolver", resolver: "acme.amazon_s3" }

How to disable Nelmio UI in production?

Is there a way to turn off all of the Nelmio Swagger UI docs? In production I want the outside world to see nothing at the following URLs, but in dev they should display useful docs & sandbox as normal:
http://ourserver.com/api/doc
http://ourserver.com/api-docs
http://ourserver.com/api-docs/*
Seems like there should be an easy switch for this in the Nelmio config, but I haven't found it. My company is using the Nelmio API Doc bundle in Symfony to develop APIs for a non-public API. The API server is exposed to the public, but we're not interested in publishing its usage to the world.
#gp_sflover's comment got me on the right track, but there's more to it than just disabling NelmioApiDocBundle on prod in AppKernel.php. Configs & routes that refer to Nelmio will generate errors until you move them into dev-specific files. The following change in app/AppKernel.php was the first step:
public function registerBundles()
{
$bundles = [
new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
...
// new Nelmio\ApiDocBundle\NelmioApiDocBundle(), // <-- REMOVED FROM HERE
new Nelmio\CorsBundle\NelmioCorsBundle(),
new AppBundle\AppBundle(),
];
if (in_array($this->getEnvironment(), ['dev', 'test'], true)) {
$bundles[] = new Nelmio\ApiDocBundle\NelmioApiDocBundle(); // <-- ADDED HERE
$bundles[] = new Symfony\Bundle\DebugBundle\DebugBundle();
...
To eliminate the config errors, I had to move the following stuff out of app/config/config.yml and into config_dev.yml:
# nelmio Configuration
nelmio_api_doc:
sandbox:
enabled: true
name: 'DLAP API Bridge'
swagger:
...
cache:
enabled: false
Likewise, the following stuff came out of app/config/routing.yml and moved to routing_dev.yml:
NelmioApiDocBundle:
resource: "#NelmioApiDocBundle/Resources/config/routing.yml"
prefix: /api/doc
nelmio_api_swagger:
resource: "#NelmioApiDocBundle/Resources/config/swagger_routing.yml"
resource: null
prefix: /api-docs
Now with symfony4 and flex you can install the bundle normally
composer require nelmio/api-doc-bundle
(So it won't be set as a require-dev depandency in your composer.json)
Now you change the setting in the project/config/bundles.php to:
Nelmio\ApiDocBundle\NelmioApiDocBundle::class => ['dev' => true]
So you don't get errors (eg from annotations), but it wont be loaded from Kernel.php
For disabling the Nelmio api-doc-bundle on specific environment, after some investigation, I ended up doing the following:
only enable the bundle on your target environment, i.e. on project/config/bundles.php have:
Nelmio\ApiDocBundle\NelmioApiDocBundle::class => ['dev' => true]
put the config annotation on env specific (put nelmio_api_doc.yaml inside ./config/packages/dev/)
put the route file nelmio_api_doc.yaml inside ./config/routes/dev (instead of being in the ./config/routes), otherwise, if you call the route for another environment which doens't have the bundle loaded, instead of 404, you will see 500)
not loading the bundle in config/bundles.php throws an exception in Symfony 4.3 with NelmioApiDocBundle Version 3:
There is no extension able to load the configuration for "nelmio_api_doc"
I ended up disabling the route for the api docs with a redirect in the environment, which needed to be disabled (prod):
#config/routes/prod/nelmio_api_doc.yaml
app.swagger:
path: /api/doc.json
methods: GET
defaults:
_controller: FrameworkBundle:Redirect:urlRedirect
path: /
permanent: true
app.swagger_ui:
path: /api/doc
methods: GET
defaults:
_controller: FrameworkBundle:Redirect:urlRedirect
path: /
permanent: true

Resources