Marcus Olsson

Frilansande webbutvecklare

29 april 2015 av Marcus Olsson

NamnAPI uppdaterat

NamnAPI.se är en enkel tjänst som jag byggde för snart fyra år sedan i syfte att lära mig mer om REST-API:er.

Applikationen har fått stadigt med trafik under alla dessa åren, men sedan årsskiftet så har delar av den tyvärr legat nere sedan jag migrerade servrarna för ett 20-tal webbplatser och aldrig satte upp databasen ordentligt.

Efter att flera personer har kontaktat mig och önskar komma åt datan så valde jag att äntligen ge API:et lite ny kärlek.

NamnAPI är nu släppt i en helt ny version (2.0), med ett lite mer logiskt sätt att hantera parametrarna på. Applikationen är ombyggd från grunden, då jag passade på att använda mig av nya Lumen för att se hur pass användbart det är (väldigt enkelt och smidigt att arbeta med, ser kanske inte så många tillfället då det är att föredra framför Laravel dock). Ny smidigare webbplats med fler exempel är också uppe (förra webbplatsen använde Bootstrap 1.2).

Version 1.0 finns fortfarande kvar för dem som absolut måste använda sig av det.

Kul att folk ser fortfarande ser en användning av detta otroligt simpla lilla API.

14 april 2015 av Marcus Olsson

Lumen – Laravel i en mindre förpackning

Taylor Otwell, skaparen av Laravel, har under en längre tid kryptiskt pratat om "ett annat ramverk" som han har jobbat på – och idag så släpptes äntligen "Lumen".

Lumen är ett micro-ramverk likt Silex, Slim eller en av mina favoriter – FlightPHP, som är särskilt framtaget för att hantera tjänster som behöver vara extra snabba, men kanske inte behöver jobba särskilt mycket med gränssnitt. API:er t.ex.

Ramverket i sig är strukturerat väldigt likt Laravel, om man är en van Laravel-utvecklare så verkar det inte vara några som helst svårigheter att sätta sig in i koden.

Vad man tappar med Lumen gentemot Laravel är en hel del flexibilitet och alternativ, t.ex. möjligheten att route:a subdomäner, men vad du får istället är högre prestanda.

Eloquent ORM, Blade-templates och andra välkända Laravel-komponenter finns fortfarande att tillgå dock.

Läs mer om ramverket på lumen.laravel.com.

11 april 2015 av Marcus Olsson

Push to deploy med Git – den enkla vägen

Om man använder Git för versionhantering – via exempelvis Github eller Bitbucket – och sedan vill ha upp koden snabbt och enkelt på ens server för att servas till besökarna, hur gör man då?

Det finns så klart en rad olika tjänster som hjälper en att sätta upp "continuous integration" och andra automatiska flöden. Men säg att du bara driftar en enkel sajt, och vill ha möjligheten att kunna pusha upp kod när det passar dig direkt till servern? Det kikar vi närmare på här.

Jag förutsätter här att du redan har en server uppsatt med Git installerat, samt att man har SSH-åtkomst.

Börja med att installera ett Git-repositorium på en lämplig plats på servern. Jag brukar köra på en "syskonmapp" – om jag servar webbplatsen från t.ex. /var/www/mysite.com så placerar jag helt enkelt repositoriet i /var/repo/mysite.git.

cd /var
mkdir repo && cd repo
mkdir mysite.git && cd mysite.git
git init --bare

Nu finns ett Git-repo installerat på /var/repo/mysite.git, man kan redan nu lägga till repot som en remote och börja pusha kod. Men vad är det roliga med det? Just nu händer det inte så mycket.

Här kommer det fina med "Git hooks" in i bilden. Med dessa hooks kan du styra vad som sker när man interagerar med ett Git-repo. I det här fallet så använder vi post-recieve-hooken. Om filen inte återfinns under /var/repo/mysite.git/hooks/, skapa den då med cat > post-receive och fyll den med något liknande detta:

#!/bin/sh
git --work-tree=/var/www/mysite.com --git-dir=/var/repo/mysite.git checkout -f

Här talar vi helt enkelt om att när en push sker till repot, så ska den nya koden checkas ut, och uppdatera innehållet i ens "working tree", alltså /var/www/mysite.com – där webbplatsen servas ifrån.

Innan du börjar pusha kod, se till att du har korrekt rättigheter på repot, så slipper du huvudbry senare. T.ex: chmod +x -R /var/repo/mysite.git.

Din server är nu redo att publicera din kod när du pushar kod till den; enklast är att att använda t.ex. SourceTree och lägga din server som en remote (t.ex. git remote add live ssh://repouser@192.168.1.1/var/repo/mysite.git).

Lite mer avancerat, exempel med Laravel

Beroende på typ av webbplats, och eventuellt vilket ramverk man använder så brukar det finnas 2-3 olika jobb man gör varje gång man publicerar ny kod. Detta kan t.ex. vara rensa cache, uppdatera composer eller kanske köra vissa migreringar.

Alla dessa typer av jobb kan man också köra via ens post-receive-fil. I fallet med Laravel så vill vi köra composer install, php artisan migrate och även rensa cache:n.

#!/bin/sh
git --work-tree=/var/www/mysite.com --git-dir=/var/repo/mysite.git checkout -f

cd /var/www/mysite.com

echo "Processing composer"
composer install

echo "Running migrations"
php artisan migrate --force

echo "Clearing cache"
php artisan cache:clear

Varje gång du nu pushar kod till servern så kommer alla dessa jobb att köras automatiskt (skärmdump från SourceTree).

Push to deploy i SourceTree

Några frågor eller kommentarer? @olssonm är jag på Twitter

18 mars 2015 av Marcus Olsson

Laravel tips del 4 – Accessors i Eloquent ORM

En fantastisk användbar funktion med Eloquent som ofta missas (om man går efter frågorna på Stack Overflow i alla fall) är Accessors.

Accessor kort och gott ett attribut som man kan sätta på en modell, ett attribut som saknar ett motsvarande fält i databasen.

Låt oss säga att du bygger en applikation som ska hantera bokningen av t.ex. lokaler (hade uthyrning av filmer som exempel först, men vem hyr fysiska filmer idag?) – man kan så klart ha ett boolean-fält som visar om lokalen är uthyrd eller ej, man i det här exemplet så använder vi ett start- och stoppdatum för bokningen, och använder en accessor för att se efter lokalen är tillgänglig just nu.

Först, en enkel migration, där vi har koll på vilken kund som hyr en viss lokal, start- och stoppdatum för bokningen:

class CreateBookingsTable extends Migration {
    public function up() {
        Schema::create('bookings', function($table) {
            $table->increments('id');
            $table->integer('customer_id');
            $table->integer('room_id');
            $table->date('booked_from')->nullable();
            $table->date('booked_to')->nullable();
            $table->timestamps();
        });
    }
}

$ php artisan migrate

Nu skapar vi vår accessor, vi använder Carbon för att enklare jämföra datum (notera att vi endast kollar av om bokningsdatumet är före eller efter "idag", i verkligheten skulle andra kontroller behövas också):

use Carbon\Carbon;
class Booking extends Eloquent {
    public function getAvailableAttribute() {
        $now = Carbon::now();
        $bookedTo = Carbon::createFromFormat('Y-m-d', $this->booked_to);
        $diff = $now->diffInDays($bookedTo, false);
        if($diff >= 0) {
            return false;
        }
        return true;
    }
}

Så enkelt var det, nu kan vi enkelt kolla om en lokal i fråga är tillgänglig/bokad just nu.

$room = Room::find(1);
$room->available; // true/false beroende på bokningsdatum

Notera att accessors skapar "snake_case"-attribut:

public function getIsAvailableAttribute() {
   // Kod
}

$room = Room::find(1);
$room->is_available;

Men om man vill hämta en Collection som JSON då, hur får man in accessorn då? Man använder helt enkelt $appends-attributet;

protected $appends = array('is_available');

Notera att den här guiden använder Laravel 4.2, accessors 5.0 fungerar i princip likadant. Se dokumentationen för mer information.

13 mars 2015 av Marcus Olsson

Google Code stänger ner

Google utannonserade inatt att de kommer att stänga ner Google Code. Fr.o.m. idag kan man inte längre skapa nya projekt, och efter den 25:e augusti kommer inte längre kunna commit:a kod till sina repositorier på Google Code.

Google Code var länge en av de större tjänsterna som erbjöd en att lagra och distribuera kod till andra, och var dessutom helt gratis. De erbjöd både Subversion, Mercurial samt Git.

Andra tjänster som GitHub och BitBucket har under de senaste åren växt i rasande takt och tagit användare från Google – och Google själva har t.o.m. migrerat över en rad olika projekt till GitHub. Men Google Code används fortfarande av en rad större och populära projekt, som t.ex. Sequel Pro.

Trist att se Google göra sig av med ännu en av sina stora produkter som inte ingår i deras kärnverksamhet (Search, Mail och Youtube).

9 mars 2015 av Marcus Olsson

Nytt från Apple 9:e mars 2015

Idag höll Apple sitt "Spring Forward"-event som väntat till största del handlade om deras nya Apple Watch. Men det dök även upp en del andra smånyheter.

AppleTV

Ingen ny AppleTV den här gången heller, men i alla fall en prissänkning, från $99 till $69 (~690kr).

MacBook

Rykten om en ny 12" MacBook Air med retina skärm har det ryktats om länge nu, och Apple levererade en helt ny MacBook.

Detta blir för första gången på nästan 6 år som en dator från Apple endast går under namnet "MacBook" (den förra modellen var den klassiska vita i polykarbonat).

Denna helt nya model skippar allt vad rörliga delar heter, t.o.m. fläkten, och kommer i samma färger som deras iPhones (Silver, Space Grey och Guld). Som räknat med en såpass otroligt tunn och fläktlös dator är processorn inte så mycket att hurra för med sin Intel Core M processor, som är klockad till 1.1GHz på de billigare modellerna (med Turbo Boost upp till 2,4 GHz) och 1.3GHz på de dyrare (Turbo Boost upp till 2,6 GHz).

MacBook 2015 MacBook 2015. Bild från Apple.

En spännande dator är det (retina skärm!), och jag tror att detta är en potentiell storsäljare – särskilt den guldfärgade varianten (föredrar Space Grey själv dock).

Priset är satt till $1299 i USA. Svenska Apple Store listar för tillfället 14495kr, vilket är en väldigt egen tolkning av dollarkursen – får se om de ändrar detta.

ResearchKit

Apple outsourcear förskning medecinsk forskning genom appar i iPhonen. Intressant koncept som påminner en del om Folding@Home, men istället för att låna ut datakapacitet så deltar man själv aktivt i undersökningarna och ställer diagnoser på en själv.

Apple lovade även att släppa plattformen som open source.

iOS 8.2

Ute nu. Förbereder bl.a. integrationen med Apple Watch.

Apple Watch

Mycket tid och fokus lades på Apples nyhet, AppleWatch. Väldigt lite sades egentligen som inte är sagt sedan tidigare, mer än att klockorna äntligen har fått officiella priser och datum.

Apple delar upp klockorna i tre olika familjer: Apple Watch Sport, Apple Watch och Apple Watch Edition. Där Sport-modellen är klart det billigaste alternativet, med gummiremmar och svarvad i aluminium – priserna är från från $349 till $399 beroende på klockstorlek (38mm eller 42mm).

Apple Watch är gjord i rostfritt stål (silver eller svart), och går på $549 hela vägen upp till $699 beroende på vilken modell på klockarmband man väljer.

Edition, som tillverkas i 18K guld och endast i begränsad upplaga börjar på smått otroliga $10000 och kan kosta hela $17000 beroende på vilka alternativ man väljer.

24:e april släpps den i stora delar av världen, svenskt datum är ännu inte satt.

Förmodligen kommer den att sälja bra, men inget som övertygar mig.

Intressant är också att eventet hade stor fokus på Kina, där både kinesiska appar visades upp och den obligatoriska "Apple Store-öppningssekvensen" var från en Apple Store i West Lake (Xī Hú) i Kina. Därav guldklockor och guldfärgade MacBooks?

16 februari 2015 av Marcus Olsson

HTTPS med Cloudflares Flexible SSL

Nyligen så bestämde jag mig för att börja använda mig av HTTPS här på marcusolsson.me och stötte på ett litet frågetecken som jag antar att fler än jag någon gång kommer behöva tänka på.

Jag valde att använda mig av Cloudflares "Flexible SSL", vilket innebär att trafiken mellan webbläsaren och cloudflares servrar är kypterad – Cloudflare sitter i sin tur emellan min server och besökaren (läs mitt tidigare inlägg om Cloudflare om du vill veta mer om tjänsten) – min server använder sig alltså inte av ett eget utfärdat SSL-cerifikat.

'Cloudflare Flexible SSL'

Man kan lätt tro att för att använda sig av deras Flexible SSL så gör en standardkonfiguering i nginx, precis som om man använde ett vanligt SSL-certifikat eller Cloudflares "Full SSL":

server {
    listen 80;
    server_name marcusolsson.me;
    return 301 https://marcusolsson.me$request_uri;
}

server {
    listen 443 ssl;
    server_name marcusolsson.me;
    root /xxx/marcusolsson.me;
    [...]
}

Men icke, detta kommer att resultera i en redirect-loop som webbläsaren till slut avbryter.

'Chrome redirect loop' En redirect-loop i Google Chrome

Men varför? Jo – Cloudflares Flexible SSL lägger sig alltså endast mellan besökaren och Cloudflares servrar – trafiken till slutdestination (alltså ens egna server) kommer fortfarande att ske via port 80, inte standardporten för HTTPS; 443. Cloudflare kommer i sin tur (om alternativet är valt vill säga) alltid att erbjuda webbläsaren att ansluta via både HTTP och HTTPS.

Men hur tvingar man en HTTPS-anslutning då? Den enklaste metoden jag kunde hitta var följande:

server {
    listen 80;
    server_name marcusolsson.me;
    root /xxx/marcusolsson.me;
    
    if ($http_x_forwarded_proto = "http") {
        return 301 https://$server_name$request_uri;
    }

    [...]
}

Notera att endast ett server-block används.

Här kollar vi alltså om protokollet är HTTP, och om så är fallet så kör vi en 301:a till motsvarande HTTPS-sida.

För Apache så skulle en liknande metod kunna se ut som följande:

RewriteCond %{HTTP:CF-Visitor} !'"scheme":"http"'
RewriteRule ^(.*)$ https://marcusolsson.me$1 [L]

5 februari 2015 av Marcus Olsson

Att tänka på: Google AdSense, PII, och URL:er

webbjobb.io så är AdSense en betydande intäktskälla, därför var det mindre lustigt att se det här i ett mail från Google:

Dear Publisher,

It has come to our attention that you are passing personally identifiable information (PII) to Google through your use of one or more of Google's advertising products – DFP, AdSense, and/or DoubleClick AdExchange.

Our systems have detected information, including email addresses and/or passwords, being passed from the ad requests attached to this email.

[…]

We require that you fix the issue within 30 days.

Självklart en dundertabbe från min sida, då jag faktiskt har koll på vad som gäller; bifogat var även exempel på data som de flaggat:

Url sample: https://webbjobb.io/prenumerera/verifiera/redacted@example.com/xxxxxxxxxx

När jag byggde webbjobb.io så lade jag en del tid på att planera ut URL:erna, självklart vill man ha fina URL:er som direkt förklarar vad de gör utan att kännas "konstiga" för användaren, därför finns det sådana som:

webbjobb.io/prenumerera/verifiera/example@example.com/xxxxxxxxxx
webbjobb.io/prenumerera/installningar/example@example.com/xxxxxxxxxx
webbjobb.io/prenumerera/avsluta/example@example.com/xxxxxxxxxx

Där jag använde e-postadressen och en slumpmässig sträng på 10 tecken för att verifiera användaren.

Problemet med allt det här (vilket jag igen, borde ha tänkt på) är att Google läser av URL:en för att räkna ut vilka annonser som ska servas till användaren – och e-postadressen skickas då med i anropet. Google förbjuder en strikt att skicka med PII (Personal Identifiable Information) i annonsanropen.

För att lösa problemet var första tanken var så klart att bara ta bort annonserna på de sidorna det gällde, men jag ville inte riskera att fastna på något liknande igen – så jag fick bygga om systemet för att använda sig av GUIDs istället (och självklart vara bakåtkompatibelt). För PHP/Laravel så är det så enkelt som (exempelvis):

<?php
// via: http://stackoverflow.com/a/15875555/684195
public static function generateGUID() {

	$data = openssl_random_pseudo_bytes(16);

	assert(strlen($data) == 16);

	$data[6] = chr(ord($data[6]) & 0x0f | 0x40);
	$data[8] = chr(ord($data[8]) & 0x3f | 0x80);

	return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
}

Fulare URL:er t.ex:

webbjobb.io/prenumerera/verifiera/xxxxxxxx-xxxx-4xxx-8xxx-xxxxxxxxxxxx

Men enligt Googles riktlinjer – och i slutändan säkrare för användarna.

5 februari 2015 av Marcus Olsson

Laravel 5 har anlänt

Det är nu snart 6 månader sedan utvecklingen av Laravel 4.3 drog igång, men ganska så snabbt insåg core-utvecklaren Tyler Otwell att det var en såpass stor uppdatering han ville genomföra att han helt enkelt valde att gå till version 5.0 i stället, samtidigt som han sköt på releasen på obestämd tid.

Men nu har Laravel 5.0 anlänt!

Väldigt mycket är nytt – för oss som har använt av oss av Laravel i ett par år nu är inte allt för vana med att se den här storleken av uppdateringar samtidigt, i många avseenden så är det som ett helt nytt ramverk man får se till att lära sig, med ny filstruktur, och helt nya sätt att hantera allt ifrån controllers, providers och vyerna.

Jag tänker inte täcka alla nyheter här då så många andra redan har gjort det bättre än vad jag kan göra det – kika t.ex. på det här inlägget från laravel-news, eller den här bloggserien från Matt Stauffer.

Laravel.com har även fått ett ansiktslyft (som vanligt då ramverket uppdateras).

Då är det inte så mycket mer än att börja läsa uppgraderingsguiden och sätta igång!

18 januari 2015 av Marcus Olsson

Laravel-tips del 3 – View composers

Ofta när man programmerar en applikation så stöter man förr eller senare på problemet att man har en variabel som man vill ska vara tillgänglig i alla vyer, eller kanske rentutav alla vyer som använder en särskild layout – något som man i Laravel inte löser särskilt bra med det vanliga hederliga with() i controllern, då variabeln endast blir tillgänglig i den aktuella vyn.

public function getIndex() {
	return View::make('public.frontpage')
	       ->with('title', 'startsida')
}

Man kan även så klart använda View::share(), som kommer att sätta variabeln i alla vyer (kanske genom att lägga till dem i BaseController?). Eller som somliga rekommenderar; att använda Laravels IoC-container för att sätta upp kod som kan registrera och "dela" på variabler.

Men, nu handlar det här om view composers.

View composers är en intressant och användbar funktion i Laravel som man kanske inte används jätteofta, trots att de kan vara otroligt användbart för att just sätta variabler i utvalda vyer.

Det enklaste sättet att använda en view composer är:

View::composer(array('*'), function($view) {
	$view->with('foo', 'bar');
});

Den här koden lägger man enklast in i en fil som alltid inkluderas (tips: skapa viewcomposers.php och dra med den i autoload-classmap i composer.json – eller kanske filters.php).

Det fina här är att du kan välja vyn (eller vyerna) som variabeln ska vara tillgänglig i, du behöver inte fundera på vilka routes eller vilken controller som ska använda dem.

Detta är enormt användbart om man är längre fram i utvecklingen av en applikation och man kommer på att man alltid behöver en variabel definerad, för att slippa skriva kod som:

@if(isset($foo) && $foo == 'bar')
	<p>Ett litet meddelande</p>
@endif

Men, tillbaka till fler exempel med composers. I exemplet ovan använder vi en asterisk, *, för att visa att variabeln ska vara tillgänglig för alla vyer. Man man kan på likadant vis ange specifika vyer:

View::composer(array('public.frontpage', 'public.login'), function($view) {
	$view->with('foo', 'bar');
});

Eller om man så önskar, en layout:

View::composer(array('layouts.main'), function($view) {
	$view->with('foo', 'bar');
});

Det blir ett litet annorlunda tänk, då man faktiskt jobbar med namnen på vy/blade-filerna istället för routes eller controllers som man vanligtvis gör i Laravel. Spana in dokumentationen för att läsa mer.

16 januari 2015 av Marcus Olsson

Vad är darodar.com och iloveitaly.co?

Om du använder dig av Google Analytics så har du säkert de senaste månaderna sett en hel del trafik under referrals ("hänvisningar") från bl.a. darodar.com och iloveitaly.co. Säkerligen rör det sig om dussintalet besök också som på mindre sajten kan fördärva statistiken. Varför då? Jo – detta rör sig inte om riktiga besökare alls.

'Darodar.com loveitaly.co'

Några klyftiga personer har kommit på att man kan skicka falsk data direkt till Google Analytics utan att behöva köra den Javascript-koden som man får från Google. De behöver bara gå igenom alla UA-id:n (ens unika id man får från Google, t.ex: UA-3150000-1) slumpmässigt. Detta utnyttjar de till att skicka data om spam-sidor – nyfikna sajtägare vill såklart spana in var ens trafik kommer fram, och så landar man på någon skräpsida eller referral-länk.

Besöken är alltså inte riktiga besök, utan endast falsk data.

Detta verkar fungera väldigt bra för spammarna, då jag i alla fall på mina sidor och de jag driftar åt mina kunder har märkt en markant uppgång i trafiken under januari – dessutom har det tillkommit en gäng liknande sidor.

Hur löser man det här problemet då?

Det finns dessvärre ingen jättebra lösning som åtgärdar alla spam-sidor samtidigt i nuläget, men om du upptäcker spam-sidor liknande darodar, iloveitaly och andra, då kan du för varje sida välja att blockera dem från att registreras i Google Analytics.

Logga in på Google Analytics, och gå igenom följande steg:

  1. Klicka på Admin (Administratör)
  2. Klicka på Property/Tracking Info (Webbegendom/Spårningsinformation)
  3. Klicka på Referral Exclusion List (Undantagslista för länk)
  4. Här kan du lägga till alla domänerna som inte önskar ska finnas med i din Google Analytics-traffik.

'Darodar.com loveitaly.co traffik'

I slutändan är det bara Google som kan göra någonting åt det här genom att ändra i sitt system så att spam av den här sorten inte kommer igenom och tillåts hos Google Analytics. När detta kan tänkas ske finns det i nuläget ingen som vet.