Case sensitive

Функциите/методите НЕ СА кейс сенситив, тоест това ще гръмне с „Cannot redeclare function previously declared…“
function a(){}
function A(){}

Променливите СА.
$a и $A са отделни променливи/пропъртита.

Клас имената НЕ СА.
class aaa {}
class aAa {}
ще гръмне с „Fatal error: Cannot declare class aAa, because the name is already in use in …“

Излиза, че само прoменливите/проповете СА case sensitive.

Static methods and properties

В PHP можеш да работиш със статични методи както статично, така и през обект.

Но със статични пропъртита – само през метод (статичен или не, няма значение) или името на класа.

Реално, през обект и статично (напр. $obj::prop) могат да се викат само клас-константи. Това ($obj::prop) ще гръмне фатално с „Undefined class constant ‘prop’…“

Има логика, константите не се променят, викай си ги както си щеш.

JavaScript-ища

В JavaScript e напълно допустимо да се използва dollar sign $ пред името на променлива, но понеже така е прието да се именуват jQuery обектите, затова не добра идея.

Strings are concatenated via the plus (+) operator, which converts the other operand to a string if one of the operands is a string:

alert(11 + 22 + 44 + 'bloa' + null);  // алертва 77bloanull

Демек, и един стринг да има, всичко става буквално стринг, даже null става стринг ‘null’

function func1(){
this.tova = 11111;
}
var m = new func1();
console.log(m.tova); // Ще логне 11111

function func2() {
carName = '2222222';
}
console.log(carName);

Uncaught ReferenceError: carName is not defined

JS hoisting

function tomato(){
    alert('Tomato one');
}

tomato();

function tomato(){
    alert('Tomato two');
}

tomato();

Will alert „Tomato two“ two times because the second „tomato()“ function will be hoisted above the fitrts one.

For functions – yes, but not for function expressions. There won’t be hoisting.

var tomato = function tomato(){
    alert('Tomato one');
}

tomato();

var tomato = function tomato(){
    alert('Tomato two');
}

tomato();

Will alert „Tomato one“
And if you call tomato() again under the second function tomato()… „Tomato one“ and „Tomato two“ will be alerted.

So, if we have function expression – NO HOISTING,

But if we have declared function – it will be hoisted because it is so called „executable portion of the code“.

Hoisting only moves the declaration, the assignments are left in place.

HTML form enctype

application/x-www-form-urlencoded

Когато енктайпа е application/x-www-form-urlencoded – праща данните все едно са енкоднати с urlencode()

Демек „plamen“ ‘georgiev’ го праща като %22plamen%22+%27georgiev%27

Aко имаш file поле за ъплоуд на файл – качва само името на файла, пак енкоднато все едно с urlencode()

Eто примерно request body:
fldName=%22plamen%22+%27georgiev%27&fldFile=somefilename.jpg&fldSubmit=Kachvai

multipart/form-data

Когато енктайпа е multipart/form-data – праща данните по съвсем друг начин.

Content-Type: multipart/form-data; boundary=–––––––––265001916915724 (някакъв номер, различен за всеки отделен request)

и после разделя стойностите на отделните полета със:

––––––––––265001916915724
Content-Disposition: form-data; name=“fldName“

„plamen“ ‘georgiev’
––––––––––265001916915724
Content-Disposition: form-data; name=“fldFile“; filename=“20170916_101204.jpg“
Content-Type: image/jpeg

ÿØÿájYÿ*§(€%$ЕРge4$@Т23r2rqХСАТ€§%€%$СА&%€УÿájY… и т.н…. някаква двоична чудесия…

text/plain

Когато енктайпа е text/plain – праща данните подобно на application/x-www-form-urlencoded но не енкоднати. На качен файл с „file“ поле му качва само името.

fldName=“plamen“ ‘georgiev’
fldFile=somefilename.jpg
fldSubmit=Kachvai

Достигам до извод, че ако искаш да качваш файл – само multipart/form-data, иначе качва само името на файла. И мотодът да е POST.

GET vs. POST

1. GET е за получаване на нещо, POST – за изпращане на нещо.

2. GET могат да бъдат букмаркнати, POST – не, защото данните, които биват изпращани с POST, не са чат от URL-a на даденият рекуест. Демек, не дават уникалност.

3. Не използвай GET за изпращане на sensitive data.

4. GET обикновено има ограничение за дължината – 255 байта, иначе има грешка Request too long (411) но то не е от самият протокол, а на ниво сървър.

5. POST няма ограничение. Има, но то НЕ Е от самия HTTP протокол, а от PHP настройките (post_max_size).

6. При GET може само текстови данни, при POST може и binary.

7. При GET данните се предават вътре в самият URL, а при POST – в бодито, като първо се пращат хедърите, после празен ред, после данните. Демек, при GET данните се пращат в адреса върху плика, при POST – вътре в писмото.

8. GET не трябва да променя информацията на сървъра, а само да я извлича. Явно затова, браузърите не се притесняват да приемат отново и отново GET заявки, за разлика от POST такива, при които съответно, няма как да знаят какво им се изпраща.

Set-Cookie and Cookie

Сървъра сетва куки на клиента с респонс хедърът Set-Cookie

Когато клиента иска да се удостовери с това куки, праща рекуест хедърът Cookie

Все едно си носиш кожуха на химическо чистене. Те не могат да помнят всеки, който им е занесъл нещо за пране, затова ти дават бележка с някакъв номер (Set-Cookie).

Ти като отидеш след два дена например, да си вземеш кожуха, казваш: „Ето, оставих ви един кожух за пране“ (Cookie)

По този номер, те ти намират кожуха.

Литература:

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie

https://www.geeksforgeeks.org/http-headers-set-cookie/

REST и RESTfull

REST (REpresentational State Transfer) е философия за свързване и поддържане на тази връзка между сърв и клиент, при условие, че дадената връзка е т.н. „stateless“ (каквито по принцип са HTTP връзките).

Демек, при всеки рекeуст от страна на клиента, той трябва да се удостовери, че е този, за който претендира, че е и иска или да използва даденият ресурс, или да го промени.

И е този, с който сървът е комуникирал до преди малко.

Според тази философия, няма нещо като постоянна, непрекъсваща се връзка. Трябва при всеки рекуест, клиентът да се удостоверява някак за да бъде така да се каже проследен или известен на сърва.

Представи си двама приятели, които си говорят. За футбол, коли, жени… няма значение…
Логично е, щом са приятели, да няма нужда да се представят и запознават всеки път. Тоест, между тях има вече постоянна връзка.
И разговорът им би бил например:
– „Барса спечелила, Ливърпул загубил.“
– „Левски купили едикойси, ЦСКА продали едикойси.“
– „БМВ изкарали нов модел, по-добър от сегашните им най-добри.“
– „Мерцедес също имат нов топмодел от електрическите.“
– „Скивай тая мадама.“

и т.н…

„Stateless“ обаче е все едно:
– „Здравей, Пламен съм„. „Барса спечелила, Ливърпул загубил.“
– „Здравей, Иван съм„. „Левски купили едикойси, ЦСКА продали едикойси“.
– „Здравей, Пламен съм„. „БМВ изкарали нов модел, по-добър от сегашните им най-добри.“
– „Здравей, Иван съм„. „Мерцедес пък имат нов топмодел от електрическите“.
– „Здравей, Пламен съм„. „Скивай тая мадама.“

и т.н…

Забелязваш ли как винаги когато единият иска да каже нещо на другият, и обратното, трябва винаги да се представят, сякаш се виждат за първи път. Или все едно като двама приятели, които се сприятеляват и се забравят всеки път, когато искат да си кажат нещо.

Ето това е т.н. „stateless“. Няма състояние, няма постоянно приятелство, приятелството го има всъщност, но е само за даден рекуест.

И трябва винаги да се поддържа, при всеки рекуест-респонс.
Може би затова се казва „Representational“ – демек „ре-представяне“ или „ре-запознаване“ всеки път.

Всеки REST сървис трябва да отговаря на следните условия:

  1. Всичко е сървис на сърва и се достига през уникален URI.
  2. Правилата за комуникация между сървът и клиентът са общи, демек „да говорят на един език“, на общ протокол като например HTTP.
  3. Няма „стейт“, при всеки рекуест и респонс трябва да има „representation“, или с други думи „повторно запознаване“.
  4. Има пълна независимост (isolation) между отделните рекуст-респонси. Теоретично, и през пет години да си казват по нещо, трябва да е все едно сега си говорят.

А RESTFull е когато за да се постигне горното, могат да се използват всички HTTP методи, които включват не само четене но и качване, изтриване, променяне на данна на сърва.

REST vs. HTTP???

REST е идеята, концепцията, а HTTP e по-скоро реализацията, практиката.

REST идеята е да се използват всички методи на HTTP, но по една или друга причина се използват само GET и POST.
Например, ако трябва да се изтрие даден ресурс от сърва, всеки пуска GET с нещо от рода на /product/?delete_id=22
при условие, че има метод DELETE

Явно RESTfull значи, да се направи приложението така, че да ЗА ВСЕКИ ОТДЕЛЕН РЕСУРС да можеш да приложиш ВСИЧКИ „CRUD“ МЕТОДИ, а не с заместители като по-горният пример. Или „за всеки ресурс да имаш всичките CRUD методи“. Да можеш да създаваш нов ресурс, да извличаш такъв, да променяш както части от него така и изцяло, да изтриваш ресурс.

В този смисъл на думата, HTTP се явява подмножество на REST, или по-скоро реализация на REST, защото ти дава методите, с които да го реализираш, и ако използваш всичките предоставени методи – това е вече RESTfull.

Reverse proxy

Forward proxy е прокси сървър, през който минават твоите заявки КЪМ интенет, преди да излизат от локалната ти мрежа. То е „при теб“, или поне – между теб и интернет.

Reverse proxy е подобно, но то е след като заявката ти мине през интернет и тъкмо преди да стигне до сървъра, към който е тя.

Reverse proxy е „от другата страна на интернет“, Forward proxy е от „твоята страна“.

С FP можеш ти да се скриеш зад проксито.

С RP – отсрещният сървър може да се скрие за него.

FP e между теб (клиентът) и интернет.

RP е между интернет и сървърът.

В предишна фирма имахме проект за заобикаляне на АдБлокер? Слагахме директиви в httpd.conf на Апача на сайта, И когато не се намираше картинка (404) – прави интърнал редирект с RewriteRule към друг сървър, който да сервира картинката, но вече не картинка, а рекламно банерче. Демек, в този случай, сърва на сайта, започва да играе ролята на Reverse Proxy, даже и без някой да осъзнава. Reverse proxy, което прихваща и обработва ненамерените картинки.

Демек, reverse proxy e философия, самият „чалъм“, може и да не е някаква физическа машина или отделна програма.

„А reverse proxy is a type of proxy server that retrieves resources on behalf of a client from one or more servers.“

От името на клиента. Защо? Защото стои между клиента и сървъра и сървъра на практика не вижда клиента, вижда това RP.

„Contrary to a forward proxy, which is an intermediary for its associated clients to contact any server, a reverse proxy is an intermediary for its associated servers to be contacted by any client.“ – все посредници, само че едното е посредник на клиента, другото – на сървъра, от другата страна.

„These resources are then returned to the client as if they originated from the Web server itself.“

Така ставаше при Проектът Х – тези неоткрити (404) картинки, сърва на сайта ги сервираше на клиента с интърнал редирект от сърва на Проектът Х.

И клиентът си мислеше, че е са от сърва на сайта.

Все едно, отиваш в магазин, питаш за „мляко от зелено, марсианско пиле“.
Естествено продавачът не е и чувал за такова нещо, но ти казва „Да, имаме, един момент“, и докато те омайва, продавачката му отива до съседният магазин, където имат мляко от зелено, марсианско пиле, носи го, тайно, без ти да разбереш, „под масата“, го дава на продавача, и той ти казва: „Ето заповядайте“. Колко е мляко от зелено, марсианско пиле или рекламно банерче, както при Проектът Х, е друг въпрос. Въпросът е, че ти си мислиш, че е от този магазин, и че е.

Ето как в този случай, този продавач, който е всъщност истинският сърв на сайта, действа като Reverse Proxy – заблуждава те, че той ти сервира стоката, а всъщност я е взел от друг продавач (сърв), без ти да разбереш.

Разни продавачки, дето бягат по улицата между магазините, носейки кутии с обувки например, какви са? Точно едни Reverse Proxy-та. Забаламосват те с „момент, да проверим в склада дали има този номер…“, а колежката вече търчи до съседния магазин.

Кееp-alive

Какво е Keep-alive

Отива клиентът във фирма да му свършат нещо и като му го свършат, казва на служителят:
„Я стой, че Пешо и той има една работа за теб, така и така съм дошъл, след това и на Гошо да свършим една работа… че да не идвам пак сто пъти…“

Под „идване сто пъти“ в случая имаме предвид – така и така TCP връзката е отворена, защо не изпратим N на брой рекуести по нея?

Брауза казва на сърва „Connection: keep-alive“, демек, „стой там, не затваряй телефона“, демек TCP връзката.

Сърва му отговаря с: „Connection: Keep-Alive
Keep-Alive: timeout=5, max=5″

Демек, „споко, тука съм, но като станат 5 нещата, които мe караш да правя, няма да чакам повече от 5 секунди за рекуест и затварям, сори“.

timeout: indicating the minimum amount of time an idle connection has to be kept opened (in seconds). Note that timeouts longer than the TCP timeout may be ignored if no keep-alive TCP message is set at the transport level.

max: indicating the maximum number of requests that can be sent on this connection before closing it. Unless 0, this value is ignored for non-pipelined connections as another request will be send in the next response. An HTTP pipeline can use it to limit the pipelining.

Прекратяване на връзката може да се задейства или от уеб браузъра или уеб сървъра, като в заглавните части на последната заявка/отговор се подаде Connection: close

В HTTP/2 този механизъм (Кееp-alive) e безсмислен, защото там изобщо принципът е различен, демек има т.н. „Multiplexing multiple requests over a single TCP connection“.

Aпаче vs. Нгинкс

В общи линии, Апача е по-мощен откъм функционалност и гъвкавост за настройка, следователно е по-добър и подходящ за general purposes. Но по-лош за голям и едновременен “напън” при неподходяща настройка.

Nginx-а е по-дървен, но по-бърз и подходящ за статичен контент, по-добре разпределя задачите си при голямо натоварване.

Апача е “швейцарско ножче”, Nginx e кирка, лопата или мотика.
“Швейцарско ножче” обаче, към което може много по-лесно да добавиш например лупа, огледалце, трионче… отколкото от кирката или мотиката да направиш… миксер.

Напълно могат да се заместват и допълват един друг, но вече въпросът е във взаимното допълване на предимствата и недостатъците на двата – за да се получи “добре изпилена и смазана система”.

Така че, няма отговор на въпроса: “кой е по-добър”.
По-добър, за какво?
Истината е в допълването, в заедността.

Погледнато от историческа гледна точка, Апача (1995) е по-стар от Nginx-a, (2002). Какво е бил Интернет в 1995, в сравнение с 2002 г.? Реторичен въпрос, нали? Или какво е сега, в сравнение с 2002г.?
Апача генерално не е правен за голям “напън”, не че не държи на голям напън при правилна настройка, просто Nginx-a е правен първо с тази идея, и поне за това е по-добър. Подчертавам на ПОНЕ.

Nginx е създаден за да реши т.н. “C10k problem”, което може да се представи нагледно със следната ситуация:
Лелка на гише, например в банка или в някаква институция.
Изсипват и се едновремнно N на брой клиенти, тя се шашва и казва: “О не, не мога да ви оправя всички наведнъж, я се наредете един след друг, така наведнъж не мога да ви обслужа.” Подчертавам на “ЕДИН СЛЕД ДРУГ”.

Connection Handling Architecture
MPM, демек Multi Processing Module – демек, текущо зареденият модул на Апача, който отговяря за разпределянето на задачите (that dictate how client requests are handled).
Биват три: mpm_prefork, mpm_worker и mpm_event

За да разберем разликите между тях, трябва първо и задължително, да разберем разликите межд process и thread.

Представям си го нагледно и практично така:
Процесът е по-общото, тредът е процес, разделен на части.
Все едно процесът е фирма с шеф, който събира служителите и им  казва “Трябва да се свърши едикакво си”. Иване – ти поеми това, Петре – ти свърши онова, Мария – ти ще отговаряш за това… Имате фирмените ресурси, които ви трябват – баничарката, принтера и ксерокса, някой лев за командировъчни…”
Това са т.н. “споделени ресурси”. Тредовете-служители могат да ги ползват, стига да не си пречат и застъпват, защото те (ресурсите) са на ниво – процес-фирма.
Вътре в процеса-фирма, всички ресурси са споделени между ресурсите-тредове. Нали шефът е един все пак. Но между отделните процеси-фирми – не.
Не може “Дезинфекционна станция Трепем гад всякаква” ООД и неговете служители-тредове, да ползват баничарката или ксерокса на “Топли мекици” ООД.

mpm_prefork – един рекуест – един процес – един тред.
Рекуестът нека е клиент на фирма. Процесът нека е шефът на фирмата. Тредът нека е служителят (служителите). А над шефовете (процесите) и техните тредове (служители) бди неотклонно core-то (ядрото) на Апача.

Идва рекуест (демек клиент) при Коре-то и иска да му се свърши някаква работа. Коре-то му създава фирма (демек шеф), която да му свърши работата, и тази фирма (шеф) ще има ЕДИН тред (служител), който реално ще свърши работата. Демек – един рекуест – един процес – един тред.
Един клиент – една фирма(шеф) – с един служител.
Който служител ще има всички ресурси на фирмата, няма да се чака и занимава с колеги-идиоти, няма “дай баничарката, че ми трябва”, няма “Мише, кога ще ми издадеш едикойси документ”… Това, че е сам служител на шефа си, не значи, че не може да ползва всички ресурси на фирмата, без да се съобразява с колегите си. И не значи, че няма да свърши работата даже по-бързо от ако бяха много колеги (тредове) и работата не беше разпределна между тях.

Лошото е ,че не се оплътняват ресурсите много добре. Демек, шефът дава целите ресурси на фирмата на единственият си служител-тред, което не значи, че този служител-тред ще скатава или краде от бензина на баничарката. Идеята е ,че фирмата-процесът като си има запазени ресурси, те остават блокирани само за тази фирма, и са недостъпни за останалите фирми, дори и да са свободни. Демек, фирмената баничарка, фирмената секретарка… са си само за дадената фирма. Ако друга фирма и трябва баничарка или секретарка – да си купи (запази в паметта) своя.

Обаче когато рекуестите станат повече от процесите, производителнността спада рязко. Не знам защо, явно просто няма процес, който да обработи новопостъпилият рекуест? И к’о прай’м? Сядаме и чекаме? Демек, Коре-то казва на клиента “Нема свободна фирма да Ви свърши работата, е па че почекате”.

Затова mpm_prefork е сигурен откъм споделени ресурси (колегите-тредове) няма да се чакат и бъркат един друг за ресурси, но пък е неефективен при “напън” от рекуести-клиенти.

Докато има процеси (шефове) колкото за всеки рекуест (клиенти) – всичко е ОК. И понеже имаме “един процес – един тред” – значи това е модулът, подходящ за “non thread safe” PHP – понеже процесите си имат запазена, своя памет, няма как да се оплетат тредовете. Нали е един тред само в процеса.

mpm_worker – Тук пак като дойде клиент-рекуест, core-то вместо да създава отделна фирма с един служител, както при mpm_prefork (и по този начин да гарантира, че отделните служители-тредове няма да се чакат и пречат), създава един процес-фирма с много тредове-служители, на които се дава даден рекуест-клиент, и той (служител-треда) си го движи. Колко фирми-процеса и всяка с по колко треда-служителя във всяка ще има – не знам.
Но тук със сигурност има доста по-голямо уплътняване на общият ресурс.
Нека осъзнаем, че както и в живота, процесите-фирми само управляват тредовете-служители, работата се върши от тредовете-служители. Демек, колкото повече процеси-фирми – толкова “повече вожд, малко индианец”. Е да, разделението и сигурността откъм оплитане на ресурси е по-голяма, вярно.

mpm_event – този модул е същият като mpm_worker но се различава по начина, по който обработва keep-alive рекеуест-клиентите. Тоест: mpm_worker ще държи тред-служителя, докато keep-alive е в сила, дори и работата да е свършена. mpm_event отделя служител-тредовете за активните клиент-рекуести отделно от тези за keep-alive. The event MPM handles keep alive connections by setting aside dedicated threads for handling keep alive connections and passing active requests off to other threads. Идеята е явно, да не се задръсти сървъра с “Чакай да се наканя…” клиенти.

Както се вижда, Апача е доста по-гъвкав откъм това, какъв начин на обслужване на заявките генерално ще изберете.

Distributed vs Centralized Configuration
Nginx does not interpret .htaccess files, nor does it provide any mechanism for evaluating per-directory configuration outside of the main configuration file. This may be less flexible than the Apache model, but it does have its own advantages.

Apache има възможност за настройки на ниво директория (per directory basis) с помощта на .htaccess

Nginx – не.

Nginx печели производителност, защото не трябва да отваря, чете, обработва и т.н… този .htaccess файл за всеки рекуест, както Apache, но пък губи гъвкавост. Също имай предвид, че Apache прави това “отваряне, четене, обработване…” става по целия път от корена – до даденият ресурс (файл), и застъпващите се директиви се override-ват… и изобщо…

При Nginx като стартираш с дадени настройки – това е, каквото си настроил – настроил, газ на педалите.

Е да, в Апача може да изключиш .htaccess и би трябвало горните грижи и тревоги да отпаднат, не знам, предполагам…

Modules
При Апача, имаш ядро и модули, и можеш динамично, само с един рестарт да ги активираш/деактивираш.

При Nginx пак имаш разни модули, но трябва да компилираш. In Nginx, modules are not dynamically loadable, so they must be selected and compiled into the core software.

File vs URI-Based Interpretation
Или с други думи, като как двата сърва интерпретират заявените URI ресурси и ги мапват към съответните ресурси (най-често – филета).

По подразбиране, и двата сърва приемат заявените ресурси като ресурси на файловата система. Вземат домейна, заметват го с document root-a, и от там нататък – следва пътя до ресурса.

Апача може и по двата начина – демек, може да интерпретира заявените ресурси и буквално като филета или директории,
или като “псевдоними” на реални филета и директории.
Има разни механизми, дали ще е с RewriteRules или с директиви в htconfig – a…

Nginx-a може само по един начин – като интерпретира URI-то като път до ресурса на файловата система.

Static vs Dynamic Content
Апача обработва ПХП като

  1. или ПХП-то му е инсталирано като модул (т.н. “dynamically loadable modules”), да си припомним все пак, че Апача по принцип е набор, или по-грубо казано – “купчина” от модули, обединени от ярдо.
  2. или като вика външен интерпретатор (интерпретатора на ПХП).

Това като цяло явно е с идеята да може като интерпретатор да се ползва не само ПХП но и други езици. Да е по-модулно.

Nginx-a няма подобен механизъм за “външно обработване” на скриптове. Там трябва да се настрои комуникация между Nginx-а и скрипта, като се използва някакъв протокол (http, FastCGI, SCGI, uWSGI, memcache).

И тук идва допълнителното усложнение – излиза, че всеки рекуест за ПХП страница води до допълнителен “вътрешен” рекуест от Nginx-a – към ПХП-то.

Конфигурацията изглежда горе – долу така:

location / {
    fastcgi_pass localhost:9000;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param QUERY_STRING $query_string;
}

Е да, вярно, този сценарий ще се случи само за динамичен контент. Освен ако под горните редове, ще добавим и тези:

location ~ \.(gif|jpg|png)$ {
    root /data/images;
}

с които ще кажем на Nginx-a да минава през ПХП-то за всичко, без gif, jpg и png