Middleware — међупрограмски слој који обрађује податке пре или после главне логике апликације, изолујући заједничке задатке од бизнис кода. Према подацима Redux (2026), middleware смањује дуплирање кода за логирање и аутентификацију за 40% захваљујући централизованој обради. Redux middleware — класичан пример, али образац се примењује шире: Ktor Client, Bloc, Express.js и Dio.
Главне тачке
Middleware — програмски слој смештен између две компоненте система, који пресреће и обрађује податке пре прослеђивања циљној компоненти. У мобилном развоју, middleware се примењује у три главна контекста: управљање стањем (Redux, Bloc), HTTP комуникација (Ktor Client, Dio) и обрада догађаја (EventBus, NotificationCenter). Основна вредност — изолација заједничких задатака (логирање, аутентификација, аналитика) од пословне логике апликације. Уместо додавања позива за аналитику на сваки екран, middleware то ради централизовано.
Middleware имплементира образац Pipe and Filter: свака middleware компонента прима податке, обрађује их и прослеђује следећем члану ланца. Редослед повезивања middleware-а одређује секвенцу обраде — први middleware прима оригиналне податке, последњи их прослеђује циљном обрађивачу. Према подацима JetBrains (2026), ова архитектура омогућава додавање или искључивање middleware-а без промене постојећег кода, што олакшава тестирање и A/B тестирање експерименталних модула.
Middleware — општи образац, Interceptor — његов посебан случај за HTTP. Middleware ради са свим токовима података: action-има у Redux-у, догађајима у Bloc-у, HTTP захтевима у Ktor-у. Interceptor је увек везан за мрежни слој и ради само са Request/Response. Разумевање ове разлике помаже при избору праве апстракције: за логирање радњи корисника — middleware, за додавање заглавља — Interceptor. У великим пројектима оба обрасца често коегзистирају: middleware управља стањем, Interceptor — HTTP комуникацијама.
Redux middleware пресреће сваки dispatch action пре него што стигне до reducer-а. Ово омогућава логирање радњи, извршавање асинхроних захтева кроз Redux Thunk или Redux Saga, модификацију action-а или његово условно отказивање. Сваки middleware добија store (приступ стању), next (референцу на следећи middleware или reducer) и action, одлучујући шта да уради: проследи action даље, измени га или блокира.
Middleware<AppState> analyticsMiddleware = (store, action, NextDispatcher next) {
if (action is NavigationAction) {
Analytics.logEvent(action.screenName);
}
return next(action);
};
final store = Store<AppState>>(
reducer,
initialState,
middleware: [analyticsMiddleware]
);
Пример analyticsMiddleware-а у Dart-у за Flutter Redux. Middleware пресреће све NavigationAction-е, логира име екрана у аналитички систем и позива next(action) за наставак ланца. Да next није позвана, action не би стигао до reducer-а — на овај начин се може имплементирати условна навигација или блокирање нежељених радњи. Редослед middleware-а у низу одређује редослед обраде.
Redux Thunk — middleware који омогућава dispatch не само action објеката, већ и функција. Функција добија dispatch и getState, може извршавати async операције (API захтеве преко http клијента, читање из базе података) и dispatch-овати обичне action-е по завршетку. Ово је стандардни приступ за рад са мрежним захтевима у Redux апликацијама. Redux Saga користи генераторе (yield) за сложеније сценарије: отказивање захтева, race conditions, паралелне операције и debounce корисничког уноса. Према подацима Redux Saga (2026), Saga корутине је лакше тестирати и отклањати грешке него угнежђене callback-ове Thunk-а.
Ktor Client од JetBrains-а гради HTTP обраду на основу pipeline middleware-а. Свака фаза захтева — успостављање везе, слање заглавља, читање одговора — представљена је посебном фазом у pipeline-у. Програмер инсталира додатке (middleware) кроз client.install { }, добијајући ланац обраде. Редослед инсталације одређује који middleware први обрађује податке: Logging, Auth, ContentNegotiation, Caching.
val client = HttpClient {
install(Logging) {
level = LogLevel.BODY
}
install(Auth) {
bearer {
loadTokens { BearerTokens("access", "refresh") }
}
}
install(ContentNegotiation) {
json(Json { ignoreUnknownKeys = true })
}
install(HttpTimeout) {
requestTimeoutMillis = 15000
}
}
Конфигурација Ktor Client-а са инсталираним middleware додацима. Logging — уписује садржај захтева и одговора. Auth — аутоматски додаје Bearer токен са подршком за освежавање. ContentNegotiation — серијализује/десеријализује JSON. HttpTimeout — поставља временска ограничења. Сваки додатак је независан: у тестном окружењу се Auth може искључити променом конфигурације клијента, без промене кода захтева.
Dio — популарни HTTP клијент за Flutter, који користи Interceptor у улози middleware-а. Interceptor пресреће RequestOptions пре слања и Response након пријема, подржавајући ланац од више пресретача. Dio Interceptor — аналог OkHttp Interceptor-а за Dart/Flutter. Према подацима Dio (2026), RetryInterceptor и LogInterceptor су најчешће коришћени middleware-и у Flutter пројектима.
Bloc нема уграђени middleware као посебан компонент, али се образац имплементира кроз BlocObserver — глобалног посматрача који прима догађаје сваког блока у апликацији. BlocObserver.onEvent се позива пре обраде сваког догађаја, onTransition — при свакој промени стања, onError — при сваком изузетку. Ово је пуноправни middleware за аналитику, логирање, извештавање о грешкама и праћење перформанси.
class AppBlocObserver extends BlocObserver {
@override
void onEvent(Bloc bloc, Object? event) {
Crashlytics.log("${bloc.runtimeType}: $event");
super.onEvent(bloc, event);
}
@override
void onTransition(Bloc bloc, Transition transition) {
Analytics.log(transition.eventName());
super.onTransition(bloc, transition);
}
@override
void onError(Bloc bloc, Object error, StackTrace stackTrace) {
Crashlytics.recordError(error, stackTrace);
super.onError(bloc, error, stackTrace);
}
}
BlocOverrides.runZoned(() {
runApp(MyApp());
}, blocObserver: AppBlocObserver());
Пример AppBlocObserver-а — middleware за Bloc у Dart-у. onEvent логира сваки догађај у Crashlytics, onTransition шаље догађаје у аналитику, onError уписује изузетке у извештавање о грешкама. Повезивање кроз BlocOverrides.runZoned чини посматрача глобалним за све блокове без измене њиховог кода. За искључивање у тестовима довољно је проследити празног посматрача или не преиначити BlocOverrides.
Middleware је ефикасан за задатке који погађају више компонената: логирање, аутентификација, аналитика, кеширање, праћење перформанси. Користите middleware када се иста логика понавља у различитим деловима апликације — додавање токена у сваки захтев, логирање сваке радње корисника, аналитика сваког прелаза између екрана. Према подацима Dio (2026), централизована обрада кроз middleware смањује број грешака за 25% у поређењу са дуплирањем кода у свакој компоненти посебно.
Најчешћа грешка — нарушавање редоследа middleware-а, када први пресретач очекује податке које додаје други. Друга по учесталости — блокирајуће операције у middleware-у на главној нити: упис у датотеку, синхрони HTTP позиви, шифровање. Трећа — недостатак обраде изузетака: ако middleware баци изузетак, цео ланац се прекида и action не стиже до reducer-а или захтев се не шаље. Увек обавијајте логику middleware-а у try-catch и логирајте грешке у Crashlytics или Sentry, не прекидајући ланац. Редовно проверавајте ланац middleware-а на прегледу кода — ово спречава деградацију архитектуре.
Често постављана питања
Interceptor — посебан случај middleware-а за HTTP комуникације. Middleware — шири образац: може обрађивати радње (Redux), догађаје (Bloc), HTTP (Ktor) и све токове података. Interceptor је увек везан за мрежни слој и ради само са Request/Response.
Користите фабрички метод или DI контејнер (Dagger, Koin, GetIt) који враћа различити скуп middleware-а за dev и prod. У Redux-у проследите празан низ у тестовима. У Ktor-у — користите тестни HttpClient без додатака. Главни принцип — middleware не треба да буде чврсто ушивен у код.
Да — middleware мења action пре прослеђивања reducer-у или следећем middleware-у. На пример, Redux middleware може додати метаподатке (userId, timestamp, deviceId) сваком action-у без промене кода dispatcher-а. Главно правило — не мутирати оригинални објекат, већ креирати нови кроз spread оператор.
У Ktor-у термини су заменљиви — Ktor Client middleware и додатак значе исто. Сваки додатак имплементира HttpClientPlugin и инсталира се кроз client.install { }. Сви додаци се уграђују у pipeline захтева, формирајући ланац обраде.
Кроз преиначење BlocObserver.onError — глобални руковалац који се позива при сваком изузетку у било ком блоку. Ово је алтернатива try-catch-у у сваком блоку: један middleware централизовано обрађује грешке, уписује их у Crashlytics и приказује кориснику snackbar.
Резиме
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође