From f5d9c3752fd134fe4af41bf518f103b84ccb9da0 Mon Sep 17 00:00:00 2001 From: SaiVarun Date: Sun, 16 May 2021 19:04:59 +0200 Subject: [PATCH 01/32] Working on Proxy Middleware. --- .vs/amos-ss2021-carbon-footprint/v16/.suo | Bin 43008 -> 43008 bytes .vs/slnx.sqlite | Bin 200704 -> 212992 bytes Backend/Backend/Backend.csproj | 20 ++++++ backend/Backend/Backend.csproj | 1 + .../Backend/Controllers/SimaProController.cs | 2 +- .../ProxyMiddleware/ProxyServerMiddleware.cs | 60 ++++++++++++++++++ backend/Backend/Startup.cs | 22 ++++--- 7 files changed, 96 insertions(+), 9 deletions(-) create mode 100644 Backend/Backend/Backend.csproj create mode 100644 backend/Backend/ProxyMiddleware/ProxyServerMiddleware.cs diff --git a/.vs/amos-ss2021-carbon-footprint/v16/.suo b/.vs/amos-ss2021-carbon-footprint/v16/.suo index 9536614eebebb255ffa875479cdb29999139494a..b614cf18dd172418b780cea72c31604d624fd3c4 100644 GIT binary patch delta 4568 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 delta 2118 zcmchYYiL|W6o6;$K9X$i=H0xSWV3nH6!N&&Ji6OQym2=nts&Vwl%gT9$*#3cNK1Ny zvDmtTV8vC^J&Q$aOS-mI>jTa8N5Maf4Ol270sT??BUbQ-h#JLIX$p@oEDC`|VR|RGe7q}D;5A?uY-W$I_R$~OVM6EySCP!G!A+st%Ga=D zGsdWf-rOos4FQuM6~DnPL*;WNiLN57O-L7#pU}~iv_yLo)?_9R$w4xaVx$kbgX4&F zY!@QA2+gHZj_raZxeD9Why!_mF*ucHmn3Y<$b(2DvKxudUjI5#w;kDnoal9AiAiH@ zFBahg>4g;AT`$lns2CI0$rGuFH6fQ`{bx^Ppe_s1JrTFCwx)Z6JW3uY zL-anXlRN<@^Q!Nk7t$QOi4GFM1>Zu>A?J|`$lJ&}$h*izM87(!;S(_+&ZBYxSwuid zFNCP2Bzp;kuaO(bH^`k6y)L+te(8T%#`>&Cfn`R>Z4|@&1DMR{PpwH-y$?50B_ylf zgUL+H0J=m9ReiR27KKAJ5=$trYk&yU!$|8G4GfnR zhRy^aYEx#%=J?-j5LSzh!BodpxGcz^ZVrZur*u(M?Li?_b2N3>bsNd9hm4`C($ z1^y~LQ}775izHZS?y+)8?UW66N<1RHZ1lpdFO5nP?8!>Cw1=#k>CGBou$tYSO1`{1 zNzLgoaY}i8JFt=yKY=6|VJi1{q~09DxS%)ppW_15(O{%PfC*cUmgD#-Ez&B4N?h>+ zY;;5k9_t<_z@>NWfhl3uUxA3Xv1A0gV>KTHOVH}2=lYZgxN62`k?JhJ19rY(CwLMXhsLzHZWG@lO$Oh zaSqotJG}n7rfqU#o!8-QtdpHh!@efjCpY^X1_ts#7?wRVP}vubwaZ?R znNjXXernOz6+u&!W1P>zFUnc1ymiKqHT~_EmA4yzw5+rj@1M7{T!rZ}DIy7xbH+aa Dc?jkv diff --git a/.vs/slnx.sqlite b/.vs/slnx.sqlite index c30d9c458d2399181c76524e2a7f6562b67ccea9..fb057e47f2e992330fe0f1dd8325ee4f1de26dd2 100644 GIT binary patch literal 212992 zcmeEv31C}SmFSb6to^+g+i{#Yo8lx*Tt|v!TV9f;iDS!&6UTPEBu(Sg)$(L3ktIco z6SoP$Nm_}vloq-{>B7<$=l}zsb@*i{6qqtFbXccl8<@hhrNd5H3jBZWy>FEz+ew^Q z|MLPp*E;Vm=bn4+cJ96B4D9a?r+7ywmKgV?91YYWN~fcCI2;tE>!m2F5&jeZmBSwf z@dt!D#oq<~ggji0juI4^dmY6o<6gJF&%VgE*LtVrcJud4v~fRuxBgH1e*K;TS!n40 zcQ{~1q)x44O_c|ox~cu)XplcSFgfmzMLPIUI2ulcW6=@vXLPhP9O1iyBVG9-aqa!y zwn49>tEabbueftbOzo!#C%HD|0F z316l$u`754_&ey`^)S>p$e!>pkRX8yf8G>Va(cd3y$dD)?`xyL*$6OJ5>3 z5f1VRWoj`FiGmuT-`nZ!_x7}V2ONjR6y9hmoSHncQ9?i#HF6SYx1qic#0X$Rds~NB z^{K<#?Ug@?#1IDd9BAur-`&=~vEJjUkqFM=tC*xS9f?ftPx~U_P?!(q%Rt>8V!FK` zB{ILn8jD}s0s%gm4Ew_oR7HucxzTcDa9TXM%1Q>JjxsQrO!4Cq3v*G3l@2-e#qhE_ z7Vx3|*&jPmxB_CN_E;o69-SVKvDQp&wwWqNpkIyPeuXIw_@Yrh(e4Y3@gvhoC%r5; zqFvp~az7W$N73hU(}3(vFa1c(xgjg=akn19JuWv@?r)pA$K`&8^2HvP`$^en=FsDW z2F*wFG|5r*I9%@R0&{8dB6e$Kr9^pGQ6ol_gjYmN>;L&X`QT(6MoDp`5{nRf-e7o~ zPo{k1@goj2cno&!gOL=*DY#RjqWUmB~dIEDoUe%{*cp zDUm|F#BV~yV2%+ngyfuoMEZJwPb8tEO&j^oQf5GLJ{Xleuv+qvJ& zdD|~HmNExLQ|3lP3x<5N^Cp+=C=@+CrDFV3L^lcb z5tcx?$!5uImb%SQiHZ{CvS?bdh%5OCHqJt@oN^Z8@-e>V+-?IIq}$~|TEVScI!n|Y zB=@tTi{yT~xUNEImZf|SE0Kb2Adhu;97F3V^zR~;1eZ3#cO?;TjyQI9OTArrI!(xP&`y@f3PFvHbH&)ix>JDMaNgjta8b6ZckEi)4tlHE+X_egMeB2lX z;ok%)Yo>PTOqI)*>(25xPk}Ze(5vz|EMOHPCt$9aq#f`@($J1M(m4cswNfj?e3CL+ zOceJL_eG0|xs#c&Isf0;aB7rl9MCwRaX{mM#sQ538V4?#1LxP$B~*L195${;`9P{Y z77c|*(+R8*8-P`AIKbbGR@2o&gq`VdB&dp&tlr`{OcvZYCR(yr$4PeZsd}d`aEy-z zhlksJ34biw8H=UjiEuP^Ae=-nl8EAqr$9jfqT>jrqIw|ZOQh0qfput8fte+I zZ6{jT;T~ zo<84cETOh$eQ5X7C7)Xi5dCJdPWb0UVGfYL@%~_IkZ*L>*9UlKV||O;>GK4eoB@Ab zb4zn;Bi{(Vz)=lxMKD!PC;}gKrHyAE;}p4>;Y8O%2Y* z=9W6AuOSe0@=YE$U)SnsZsGy$Z>SG6wKO}Spn$V6&=hp~>V0l!L$IZ}(I4{F2OERV zW`Bb}=m|DBTN;|`fu`o56N+ebHaFIX>iPP5Pg9`Y*;40eX!ZaR!6tX3v(X*$K%~|N zr>CW{A;dQ|@V=IMr;o1(Y6Bi;fUmEENI{>o)$OZ;;u;%$%}pMlCFBe=)weV?2LjHf zW?zf5u{F@-^tA@-pw@h-p{X_4;tw@Dfu6<|-c#ocw6sET0T1tNX=-Y6HaEHX`XEqT z=jNTk)_Qk+z!P+~HhX-K6Aw8xdm5beAx}$_KjaV9HA7CJK(nXS-Rf)!`k;3H#(>iw zZ1gzYO`c%AKM-mPHMyO9sI`Unx7IoRp;kX|92&^)_tZP*@lnJ}5g>-w^bB z{PoV}U|kDo7GHB+tI#a|Ccd#D;0!efc|;==5`+fk>wQk2y8%kCuXp?1&8@&Meo2Xe z+RR}Qf?k2n4%%bsXv(v}V4$20?FrtO;)A`3p?DDeQRi{Fn_TsE^=^l|af_#UOJfT~ z=~=2h6A=28Y9!Let5m+O4&$lV*`*P4LC3308l!Mxaa>xXH&E@RxK^a*$sth92x^Ap zUVifMktI3ze;YH)cN?orCb4O84x+{@foxZAkLxj6jP{%IW0IG}Mr z-Jq9o{d|ar3lag| zuzRtAc9PhN>ykn4hm=t_P*FlV^|@Dn^^-Ooy<8`3^NnRRlm_}Bd_9+38Z!Z*Hi3c) zJ!BylOd?QES|N&&8>6^)a9`)nb7S0xxnIt)dRjD%0~!Z34rm8-i~*M^K0^k&_(yC5ZtK^>5L6U4BZZby6kLU+_?^nHeV0QyDr z28-$vfZ}a_1NS<2H#flzan0OP_Al&L*blR}u`zZpThA_IUSghR?qSl*^-K+8w*T7x zZTr*qC+v6GkK6a!8||gGpV^+WJz(pxRa;-Oe$aZ8wa>bdd)i7_p0|9?@|fjzOVo0} zvdv;Pf7bj~^9l1|^EUH(Gi~~r>FcJ?m>w~mH-$`lObw=`CcW_``3 ziH(M%1l#$$FDyxuoFXw_5Z=-V_^k~h$jS#+v1F@(xmGDKA z<6(Gq9g8X>tvY6;YEfz&DGawRQ%U9bwMP}1B-8$6AQ6tEm(R*btHY%6a3<0XLj@@- z$Ba~sSW1%jB?4p0^eaY<)CTc$Ja&RlD8H@_DRPfZp!=o#31x(pydrmK>sT6HX_WY| zJZPlWi@BrE%8x4oilVWcsJ{9YU&B#-`&67;exst;vDi4TOuBkRQ72%1 z$`?@cedP^`I{DLZrB%(7BZ~BXbiEcNSy{l!VP*P6>_k#s{$XW$J`!<8)jVB&y&?i! zNDT+z9;&i{6^9g+_a&eN<=55MsglE2XF9Hou;w5UY%DT3xf69RWt5c%6jktz!hoS7 zVC4|`441S5$Dn1LYMER$NCaE{911COuNpvo(PHcxhpb2HU41>fdc~eo)vx^KR(&hq zZ=@>7m=g1f2^RN}&Wmc3l(1F3q`L>xO5>C=jkoAB-iA;TGN@W?8Y1 zj7ABNWPE?ji+gNHmB7LfABbkPL zz*7(h0MfUz9Y(4gNK7UIjbc_6+X-#)v_BG-(aWzTJvR=Q&_OtWv{+P1goQ}Q-SfPM1#nBN9r12&3crYa8)X-$4h9IZTaMTxR_eBEf z2)>cu*4O162#@<<(bd6^qk%RSZ4isE^ng%N79$v|>DcFWjR(aKOBz88DYG$@z>5b7 zzq|n$26$gQ?Cd~&2=4d##6(N$fhUlg%oFj;GB@ECD%_1ppv})OrjM*x_qWQ;MBvAL z;V4|+Pi}$_`k(x@+rQprq*|du1KyE=ILzBH&GCG6q<_~=#KGlaw5yy(YAcD>4HL=8 z!7=nY7GjOK)$wXcyg_GjESyL=f_xI%%`xta@TwNsc(sw*4*BK83&FM1oS5z!Befru z91EpRz@vIcTOxo852VuYBX1+MZZuLpNP}F{-szt!R>DvNoj@3B#8gXH zkiJ2dglLEq1-NWE%wEu?g0VnS#8p+na0j>!J`#r26|$oQ-^kj%Vi_vHjCPa*_A}9`}Q}Bk4mmXQUc{T@hb88WK)@ z0(A#STz|9G_9N;M{f}+jZES#D&V7U(v^{5ItbgVHWP6>V?f+%F#Mi-PX=e#< z`6_+bdM|Uo?IzntOwA?Rtvf6umfe;H%NmQ_{0H-k=C7OoxA_V4edhD#g!x8uulXAD z26Kg3Z~7n8w@jZiJz@F0<^7hoTkEa2TGyN2VZ5*8nyJ#eB}+|fET6VoP3H{vT2qEI2HyBx!*{IDT0d3tDY}_<7%EMrhEMB%% zN`H*AFu!LftskUq%%_>dw)d3KmcLkj&AwQ2Kl@$F_e~{+Zi9zgN>v{iHai zDfKqg6N~9ueIH&o_v0N3j9k>?OX$szJUjst>HsWFh?;w}Z<<|rKK^QFd;)VmP|C;$T_Fz})5--S}7;7tyi*QrO*uVf@WioZRw6mAM7 z$*A5XZgfzzhtY>PQ39$yJftfBon`a}J=k>PM`H=0xCas0=_G#;h>V>W2;YQ@eFusN z*a4!4LPflNCB03opHOWyNb)Dqu7-L5F-3^2K;Mt(lF+h7jJj_b?a}Y!qvl0=2lT_A0 zx9bOBdJd!x_!8mi5i(VDv%W9Pw~v7)L!I_kRoS>KR#N}bq|PA{XIbseJSQJM28^d+yR_U5IuN0(1KdlS~G=V)Xn zZE%fF(88YN=(RfNT%zXngoUouMbK(#0>u(EtZ6H~Oh>e;DMYKNNll_Sg7!4Q(5rQl z#`HMKSD_`1qkIEMGa6e$yLDLF@xyRY8yZ#eU>wy4E0%J!o{@68R`?)kI*&<_bF`aB zQRQ(i3XNvC46Y3dNI{D^R!VOmC{c4cDy39tD??IB;1AJI@{8#8Bqc&YM+!<=VIBe| zAYnx9qhH1d8b_a$ji6<`Q7Ru+TB2rgL@Hm>Cf*>$Q)m#6$niw2;jkP}))XF=kP7YK z^%8NSM(~g#nxqB14mBd?qDu33P%2u|_8mYdS%ru6gF~nhWfa!x4I+8L8aATI8<2lv z?Onf_u0V1b+m8eZm7MHDQ52fFUPNfFHm(OrF44g4Ljo#k-MW#y;Z_4p+g|iZ(yr}M zieeY}1eSeK|KE*D$C|TUEWHKDV}eri|J+jRw%Jy%~v z@7K+);Hh!ZK76b>H>J)-Cq1H5YE@u;hfYNED{?l-&6rntbCukT7oo6OkLIAfN}6>m z=xrda`86|ZSJ7>{!rGW>G@MM=z^p+XfM{JDsNB4omepv0QEOLLDZ0T*XluOEO~g)4 z?h6ND-;cC!)CW+HQYuWUP$JYDKufZW>!r*fD@)hW`*bs@C6ED=O0^6wLG-9K9Tkur zSz!VVXfe(wWJ+LIp`NUwTXljWAV;H7j!2kIi&2JpiMYxyB|nI^Vo@dCpv$A7;1JOu zM}k&@MRRCAO$3AD$=V0IkWA1x*ti#|jbdMezwP1Dg>jNxg`$TtBR9r1Vu2|Um@y;H^a8fjP%4ty4(USYGq%e9II`=g98F(e|9_}H|&wZSGKX*Ue z8W`kyxLR&Kx0+kVm2(VdVxMKd!0qOCa@TN8?AO_+*iW(_VV`6lV;^DP&c2O(Gn-+j z*qhlj+%E`&=HUo?klhbA4ZQ4jwv}yQoy;VYWX73M#>X6HhL~Qai)ptXwFm6O_91(Z zeV2WQz13cCueGnUue2|*b9OVkfnCEcXDe8awXihvSLP4QubH1SKV^QzJkNZS`5NzUQeGNz2NF$Viz?XTH?X@AN7 zWBUvCZ`!|V|Dye~_D|aX(f)q>yX_C!@3FtxeyjbA{UqFfptygvQ}X|cWZ$cip>aUt zfW`rh0~!Z34rmD*T zn4s=NL7I9q3GP5ain<*IN$NHdya@#fDocV432r69EhIQkf^#G|OM)pB9H-t`LhE$L z&tUil3{PWt3c>iz2*z&0a1z1JlNg@Ba00_LhA9k_7$z`0j$s_b7=rtw2=pK4D25>nc?^RX1~Bwv=)>?v3`a1$0mCC04r6#2!|O3TgyD4<9>nkfhC>(* zBG@~CVLyW2{TTLP*o)wf9t`(k*p1;{4EJEzh2d@tcVXCxp%=pr1h=Ji<&R_+|Tm3h?`VXx*sVSU(o z2lr*$6L7=-5$nHOKWvZL4q1K#_5mKTe8YB!?d@EYNte`@fS$*wGd`?;pZPz{|7yIW zwF>rrEeL1%2SR9Q|KKR_oezoxIJuPyl*{b_5z zb-Uriy5H!Y*S})CihhUgUarl4t^PFoOXdq~zqMZXdFCv$!gdY)ie=PtJ^LlY9qcD9 z?Z&0_TH4B)^?vp)HmUEoSHOFQwYJ~ezH3O7Wb`{r!X+L0Z|k4ZyBHm_Rr$X>gY1Q( zHW`NW;^F4Zht@E1FEP~Wa?h<{BwuRS4CvgG>wVN?l?JEuK{~tMN4=Lbtkg-T*ZZjV zlpEITROi?GsCQ$W@&p^^1DsAg!|tXY#lOW<>~89jDnkPd%hS)XVb;K(kn#(Zx5|_3 zJ=8-gYW7g?Tx{5&Q=ewUAVGWW*@dP{p4lfP6bTglU!+K&RG-shx@Z)DHp||R$or52L z0}Gu}Itf31dO1`-|5^C)Q}|on)A0DsRUoH%&%e&%`@V zmKxT=sz;W^&J#96rH-77cTV8A;@hLN-LOn2oQ-#;F#Y1`cxMvF6kiu5IKyh4PC6m) zJdR6IoRN3NaVhweyfd~Gq%Y4o`TnSiM}6bCuJ|Z6=d8RhQUOCHIi-cyAL6^9V{(F= z^YXry8)}4nnN1E1sqI4J+cxr|Er%Wwhcvz3+ONSn))??~pR8bf(^S9d7dJr|NwNWiq65^}Yib zDIcR_b`9YsmyzVf%pjID#p!zQfC58a$Mjnb6DPdfPiF z+s7zICmaOo?S|!)^aHa?{6brS{pheB_Abolm_Jdadg-_x_7<3NiUWJvLS~!%NA^{< zt6}X>_|U%U>Wzl|x;Y%%SJl)Re6Vwc1>D>Y?yEL#HjL=zeso{8LDAlM5AUn4QndF) z9N$;1uQD`S3LN0Cf)!)I6a3X{9fmgD3}^VOs`2nO{S<%I8r+41*AosrZ|6P9U$z<# zY3j55Wvj552pwr9$O72_sE_lpP^_oa2l_anbfQmDRvnV4rB@mD;T6D)UP<(oIek&T z1QVw|*w@hvrOpJ!nr?f#zUd%>tl9xpx3)V@_MpB_=~Tg^u&94PM=h z_W|&}pOr=#nt{EkiG35r{R?*&cOBGd~v9JF77PduDT}h z$T(Cp7eABWqOsNGt_QDrb*=SHO|a1(s+o(6&YX1M%5SJHio z_Ww=nZ4`G1Zt*|M{*L`;_BL+Kb`(NxY+rMM~0=$@i$o?jK+U~ROgBSbj!BfCrZ7(rU5%-tuG1*DRj~PXceV zOo1?wI}|wZQi5@B7jTu&x0HdC5{!F5fddyM7Vpc?9F`R^Y(t2*%wd;)09Hz}*PO zy+wfoXCoMQrve9FMlkNpB5s?p3|x$0+#L!WxE8^<+Z8x)D1vdfiMWc_%i09on-ngfly%u3hcKd)R+PVzBUkQR6tey;E7UjtAS7<1q%FU zAQadEz}cf%;2#5_f+Fe@50`@93xo^D3DO#2?C+OU;#l@O_YKQ2!sOb1riE8Kp+&DGLTT<_yM87t^r0Z{%xcboIW5F z7&(wo;N}6Lz@~wO0!I!A)g_|7da@K8I3QGqh>Knuu21-Y_^nV?_UHy5)eg|22{B% z<$wJoI{!b!e1YPg;XQ&-VJ^R&#|Y#8eo(iWp88;freo(+re&Q zo7m0lMzHHw#g?;nwuJc`SoQlA^D^@jAX)pTaX{mM#sQ538V58EXdKWupm9LsfX0Ep zHx3wSy^eYk_WU~CwXmnx>9)c)9{z@%JN!L@KRaNLbxqz=Jjn-M(f zLNM$^aBLHTqu69%2%8M#YY--gO$G+A$w2>A2;*Ci;En4L99fIt4cKPjku~V=VF!YT zvCY8iSE0WTtwiv;6$l<&j^KeR1c#O(IEW1g_F%(-UD$A7M+L&0vEe{7HXLZih6Bq= z5xyK74rH+5K-fS7#>OC6i46x<+8F(Js9JqBZGVsbG+WC(Wjba3N9$p$-SRQZp!qN6 zDYMJ;L36V8tz~Y>CYPW z(to5sNbl6Yrmy~c>x%zB*7wNyNgHLUoic&FN@DB&V(ST^n0!(Tsy@|N+ z?`fVrkfj(!VoM42nPp0^25;^2kC$iXg*Ou^< zVOp9p8oJjFXsv>&(@C=hKi?^QZ-JAa98mlr{CFt!&%*6lA$| ztIiBr7D!zH%}`HTY^J*N#~_2%;65580gSMKM{)2#EG7{xut*;)_PUBq=f@z)a`0dc zNrV`=2?VsozGTtb^P?zwt)*~u`{J?{=R+tKcu<8*h1`UIv6tCQe{-G>S}9#^EiM)O z_a#R8R44eH_7s`ff zlCJ5tY<8zoaYz&gS7H1wS`Y*NU-26->%)0u}c@9_GhNYw+b(dH+Q@zA>E&y`obSmY{ z1*S={TV*kO@i$Xux4F(m@+C-2gadq1PC$M$S5WoCW-ck|JBNGdY1|kC;LK4aej=%&>~-gNGA*UE7|K>%bMo9#;P$Sm z^`r|Evrzd{$~7b`nys9f^0JgwE*d%)hN9O_;o9hY0bpWs5T=6Y1s0@8X(}nJSbF5# z801?!g$5a9M04B+18g6dG z1fQveFRYw0w#??ER#T1Vjzj(p4XQqgN4CcE)&gIMmprjN#W2V)cANe4)TX(1uS4fz zsEE_buAsD#CKiE~La57&9Y7f;AI?&4TeRm~6!Km>PFiCO=7RP}n2$;;h#B)7k>i_6 z%B|}=&Y?A1!;rESltj#h&~kIx+H==KHo|laeFWK16O#%*ZT7Mi=MJG*d8cEW)yAx+ zR#KMD2bHu)ZP0$+25Ad?l=_PlJt47FMloP*ZjfrcpoPii3U>c_G*)*V!er%LU`Y#D zMU|%;&68r;JD2S^e-zcG7t04wNES$9%Zb@cTPTSUEcTTZE$73K#fDv~EPTkXb)n?= zqs?Bm`l@q>A!&sNC*9`@ODTk=av_|>#;$-}P&G8zD2}*`PYv=(Nz4decb;bZpOt-TkeR}ksC5k+lrk0Q;xWkGmXyByQSEc@`|^Hi<<8W!IDZ@1sXeT+H8yv}^a{t9!O{ZTf-JjT}BpW+U3 zA;!U-2Fn0n;qJ9ZxtF=$+OM(S!jy0g%(LL9ZztQ!{0E%RKL_XeYwSO;KgXHb`|bPL z-~a!(AJ*!maX{mM#sQ538V58EXdKWupmE^ulLLYqdF7FgezKgd(St@wvE$W`+y6*e z0CAMJ(aZGY=tO_gN>}RffrNgdif%@pj;3#Z_30J#R=r{)qda8Nr^@IJdf0;DZ7|-Z z>ce(=xn9@+>&KKoM$r!;Cw+)vS}BH)s-QdT-|?h$5Fn*?q1KL+DKbn-LDXD1Rg85;ksWU>J-W;-7gBo{2%C|9GnTF zCR>T*231BJ|9b8LupoFF_!0aq`*Zf&?AO>YvQH5PYEa{V#sQ538V58EXdKWupm9Ls zfW`rh0~!Z34qOrku*dr+^^-z)QV357;e?Ua>FxSa5`+Y7S_o4JZPR@p1&p300Yd^i z32Y>=qM%&&DtCr5pg-;UF%*>PUL?VPp}?klp8Wbb30@(=%OrS-1piHfpON6F+!Nd* zB+GK$uMnvYtE~TRJz)8T z#bbV-xx(~_X}R$u#&snRmzWK=8y3-b>i?uaqp#4Nr~XKtMH$ZeZ>r{8uQi#0TW2~Q zHFb!hbhO#!8dm;aP*gZN!x26?9E_!+d}=ruJT~lcf&YiPhT(zWvE=Z+a3B#&#zHAq zk9W`oDAz&Wk1nAj-Q>VzGR2Rhi0D7?FB^*|4O8X}y7s7}&eHQ)Y`^cOSVAfa|8jvk z65LIfD35E39_ARUj#5-C1NbkBVeUn&$! zj7vhQ&%g~Y)Dur!eySu|rcq(Zz|B82KEZ4;Z{t$|v6QID(Z-7`8O^|*(Tg9OR5L|; zEWsm5*qM$7BYaR81jUl3s0>^@MMWjAK(&F44nE|ACmmfdTZuFzGuIIk=5ul^#Cdsg z)frw?XmIkbTpir#DB%2&BI+C zUg2-)&_pp@5BH?uoQ6QLe_ApJ2uZWc;DwR2ZvfwylxrZA4t|pAWTXp|BogDv3=v|E z%rk#PVuWdVxN95@4+_@6(ct*FI8h6qck(c1@Y84|X~{={a6U6g#A#a&-O=mN5#JduiP$7r)yM5emb+C@QtKbE>Pibm_^ae zb+SgiIN=l9TdtV0oejQBA1U9H({6aNtSW!*Yh-DeN)~;5rZ>NATuK>e9iCH8ZKek| z#XgF%(B|Bx$n|yJoY{wC^Rve8;3xPEeOq~BD9Ce0k@4cJcxruttU7pqdNfZ)7%yhy&UD~xV2;dFpZo*W)tPpj zW^dj!J^YCjJd;El$~_=TwV9nba(& zz@^#M0IRaF?WHO+AqE1giKe(FIQ383-)CQB+iShka=ZC^Cfc~4z8m)R{rWu+N&Ba9 zV2&Ixe5CTAQ#Z9AcDVe>fyr@yECNg0Ff0IJIv*i_Mn{oGrz<$pl`j(4-tTQ2^g6nF zI=t684$mo%BaGDn|9X3-$3NoOcvxNRk(#Lr##Gr3WbVpOW)D2)&QBaW3vqJFSx7<= zk2u7hbjnMDy^!9su+Pwpg!(s|=GzB|=BO4_IWKkn0fp#0}>p+YEHng{OcvYV|yxm^; zlSm9b)eKEZ3js@^s)E_%hxB_CN z_E;o69-SVKvDQp&wwWqNpkIyPeuXIw_@Yrh(e4Y3@gvhoC%r5;qFvp~az7W$N73hU z(}3(vFa1c(xgjg=akn19JuWv@?r)pA$K`&8^2HvP`$^en=FsDW2F*wFG|5r*I9x7P zde0~@mnJV_w^mk4ly?<1Vnm4+5iza*=kMf$lW`a&#gR%ZLhN~i;c<9B=^Kw9aiGCt zuxlTTq%d9~NpxCFm78mHXE`j1VzDT{5d=g8ArhYE{vm1R5#vaS6yha*6DkIC zjEEs5=L{s$S3%7*ZR9^onN5{7HM(X|b5Jy8ZZx!D z$TvH0g6RyCkedL>^3+bFsqz?%e3SCXr|5-3(bH2Z#y>@LlTaUF36z^`mfU8k+YFVc zC{ZqprWK30lAmDXECkCbXCW>h<7>|CHjqKOT^^(r+{&f1MBPDhKP$RO?x&0EDuiZP z%IB~WDcA<`Sck_kw4Or$E@DY=X(N1B67lAUV`ta&Wni~2ndurKDsO4#TJS;|dxla-l z>a;a|dSfLRYdVA_CwUy!X#7Z$Kc42JU_(RwlUB)1&c}^W5dKY&vSwcA+zpwA^y$PA8> zpkYGwIW^|!?C;$-tyH<^!g{2)NB&8ulz$`2`&@a*Q%C6>a9udL)3U(ipE~8(FucJ5 zL7z*iCe%Y&>(rQ>meen&DN*b`IZjtk59~tsz`k=DCs54J0oc~dv7s{4M{UP8B|T`+ z5!nty4r3KtcffV^rX0GHl3*~_nTVYWkw9u8+NQS=2*avma^kJOw$S%w#|Z>r6iqfsI` z0s2*;9wXHs6+@-^!^Mr5avl?<(mLSfVLu<@ zVK4~rBhp_;9z?~XEF042#f3VH6eE9DdAp0023kw{n-BmShWbUb5#7PZ;h@qNP0d1d z`RqjJ&1zPnb5b3txpg^bss#IJw=1+IYEI|j>7qj2UE)dJJ}-Tp-f`!!ixu@JVzAISgTZT2k`digKC z?w4QwBdY)pbN6$1ac=^Te>Za}Zk!8oBjE3EKevZ#=dR&A;O%b%=irucWtJR(T{yW)xvtw4)r>!DYNbg2-0TV;}As6 z=mD|W0N&eB0N&eB0N&eB0N&eB0N&eB0N&eB0N&eB0N&eB0N&eB0N&eB0N&eB0N&eB z0N&eB0N&eB0N&el`bynDkl;yzY$ZVp37SdJL;?>98cEPVf_f6TNl-_E%_MM1ql|DpqvEwt+&~L-+G%3_^r3ufZuwX4ft)l*?`}+n+^DFyV+nP>G0cjv%x}s z35{wZzl%B=`dfUL(Qp zN$@)o{FVg2A;GUnfFH}7Y5Z8;OykG$X8M1~w^vEKj;Mxuzlb?*mw zR`))Dr*uyMoX|ZEFkV7adc$rEcVXCxp%=pr4BIi>iD4UtJ22di;k6iU!|)mmw_>;j zL+~39`GenhfZ#Wt((C>K!zVEYe8>YHe8>X?AMyafhde;=ArBCI$O8l)@&LhyJV5Xv z4-kCF0|X!P0KtbmK=2_C5PZl31RwGM!G}CR@F5Qne8>X?AMyafhde;=ArBCI$O8l) z@&LhyJV5Xv4-kCF0|X!P0KtbmK=2_C5PZl31RwGM!G}CR@F5Qne8>X?AMyafhde;= zArBCI$O8l)@&LhyJV5Xv4-kCF0|X!P0BsmrF|=T4#?XYJ5yKJ;4H(iG>M_(|NFhl7 z9}NG7;a@TQ3x=;__-73NgyA1C`~!xsVfcFte~003G5igNzsB%a82%E&Utst@7`}?( z&oO)j!b@R{XaeT8X9G)x!1YZEZ?&1F~4ZO7aUg4>EGGs)^D;vd)|=_3 z#z0+DL!i}J$Je`^jTB{mMfm<`7gaOudsCpr>8tnnosEsWzoo(7=m`aUU2yX=5(y{4 zzdL_3y3Jt?;N2-0 zdFpoc zg`dLrD?YkM>I!{u=l@V&C`J89!4&oRvuY@mRf8%kxzc0d(J?-n0;`LY6Fvpw65`F= zE$v%|hmkvu=qY?HpVvP$OI8QRLbdkGtST;xM*A38h1pa_RX~z{_{A z&@{>?CJ{Bm)eB8eI)z#!Odfo@+Wg5>!WTfs8Ir|FUwbTe3|{{fCuv~vstB932ubQ~ z1F0(-Ud0lk>78O>l}u4zED{bB$4CLwZafx+u_Eb0%_q}%dAYXFgRB`1xhb@u;DarV zp`gd-Y~*=ZP&Br*I$MLmpwk@;Ha3Mqt<52KE4JVV4@P89U`hi~!A6|j)-G6#&>oM! zxjE42cD6QqAiIW!0A%M0IX!%f+Y@qo>OD>MT}iOiflM(9R>EMGI0}Y@$x#{CN}N+r<4Qv--`Ld99E25F zQ!wOg^fv{aEiHAe&c>z|-XCmi@Vi@^g&LwaYN%>SQdRsXR1^P#RhVduN;2t1tWhCG zwEEnw?z)DM)7=zmhOC=foPOTZ=mb39>}w1)dpu3RC5PiQuqu1=N=#tw-LU)w0vm%3 zd_#-h*${#hjrH}7PJb&<$v3zI0k^Ng*WhsvfW;9sL*Z9JQK2aWs*^h>ccsHY1)(=L z*0nXY@2qciwzb#obT)cg+|HKHmQJVF+tkv~-VT(ux1N?0K;6*00#p&v@RnG|Vet>a z^p-exLlW|q10EN_>;y><9}!ldI5+eHQJ_yCE(+^OMGPWSDxpQW2)st`I-vj%HDu)s z8TnFwgRiQj=%p4SA19G%#Mz*?v8wNa;k2A+UC}@!9pt;BxHmy&sYIHW2*x>ymSM%* zh#fcFuIM|ot|ESQj+L^xRX|9TLz}V+ifj>E6eR*v=A{ziGa9)z)#|3Ko}++Cw2A3O z#tA)1CSHsn3@mOrB~%v-^GxuffEMb6glOnqVk=ZD`iwjb3M#oE@u+)F?GJ!(`vc;@9TtFahXr60h8|@9ZzH(tLUiLtZI0|9?7gx2F036WzZ}Y5xDfu@-+KmN+J|MDzbA`^SYtDaGxjIXlPI{QoIk z5{fSOq^nz+|3A(DpXUE>CLf35J;~&p{BUdj|3p7}n*TrI8BlcGr}_W8V*dZ&rkHSn zNp;hJM*II2)EgM@$Qku%^%N=}A#3Fo(hl|+6ymQheL^Rx# z#kb$C$Tp%q5lbd_@lmPpH)Qe6Hfkz%`FVgZXM$UT6!N<()_%&GU4dKStm*Po05#_m zz7#L{?Cwv)weoQVHOB06A`{>s^>TX-7pZAWCi!uHWU?z7iphM@Wvd7!>B~|wQ|x1vkz*Q=6`!9xG$DAg06k! zcDJi7lmbuUA~k%rjBp{>i8^+aeGnXW^&T8hf{P#CzM~_1GDF zx{Dc1RcBdJC%6kaOLw|B21}weO#D3$q|(7~Y*>^l!NTLULvwW5*uFqNt#Ro4F#TO|R`6?w-U758Is@Gg5s$tqt z@~|TY4}TMAG8y)#!;zqZy}~DHFsRF#32AWa`mziL7s*h8&b(qmFCGpyZsDVoGbSK0%oE2{~5AgzY@oY)A#=wVS&DI z`~M7CqZi5kKSLJoQwzWU&j_pb1>OH=gcbelgTN(kpgJyO|DO>S_rQSARSWaT||+4uh$VX-{BBP@^SY5zav$nGW!qJ~+QiF5B)uD-M%33gl+E!@zD~G(5*$zUUbK%JY(m>&uL*SZhJ0Z|>c?lek zr&Ih~ScoI$5LuGliHV##eL0B~`U41e2+7zmB7*qrcE!{Flj9M?R7tk&3J@agL|vlF zTI{MRGSnE3Wp@xdz!b+Uo8gNXL6BYp4PRnupwZk;grsORn&d1@eJbe6UQ4LF{MxpB z8UiqIG7w0F<0>72gcRoj<*8~syN$GBUWI{bkexOY4|MEJ4kNP;LYa*&_cUFU{8?(s zVD=hPGvn(~g#cVcB8GmCOE_t@ZW4Mccg%0SyrhiahrHfIoK+<{ocO*-b3g;bw zFG?wMoo`%moTAI>NddF(0H<-3h>=6k-`Cf{=?zkgrK920yFuw*yO~i(*4ij;< z?ZTUNPDDsUlKRMjD9762fT=C&i%cfNN-e1pEeYTovJ_$0?5d3UWEUDpiD+)loWbWi zq|fD^?+E8S!lf2h8texerphvJAl#jOA3L8k3&$lw`yU{^O=9E}ojFZ7IeD4dJip)x zRLOHg<`iMh!psc{g{*k~MdpS<)s2xgnVSifvoCWlt_cft5P>EImF)v#zC_%WkH|%t zn+TERSD;1vW68*5zGLZjsUE$GzFi9F6=uCR9WXye`Ds97M zHlXnx9~kw9LJ_cr+wKGFyz*FCl1ULV=5qs4fDEsw5s+?YD7LHiOp-{6ZB{9{WPS+O z=DLE&Dr+drC*bNDxz;E%#+peGdS+LFT{1m`c=IB0B`-C{uNXCGgF{X~)%!k~H-=1{ z2+hrxzpaEzV!i1U?30mAHigWTWMYJlDN8P7$cf9(5Y#+mOv_nt1Ty1< zh}QWeB6rI>nu(B7W?xXxytI{6llX^dr-D{aKc~M+_aR*=B%JfVskPaygbA~c z2Mf?*QZHYY-9pG*zmOuYZYzwi{Lg|KCDZPNMM(7|{$fA5IDO{>Y?g!-luO<#=!+02(ZjH&$ zL#Ar8O@z96RR>=Lb^9g);K%?Bjbj4)e2G*NE(`=>peme{7glStU?3E(*q)ue%U)h) z&iuAxRko3kxp{%x989f(TLl=G(XtGTrc3>2X|{n-xOSl_48-Dmusx}wt-d&DLp=st zo0s{vGV3O^X)-%M9eQn+bihYlY^g z2crcm8J!F0U&2`zrf6#Rh1&&Fl)E`NopqA3#xK5g$n92gPkYdp1Va?)rjBrglmDZV z{hQ{W{loAqB{F#va+s5Qsad7Thl>wb*^gq%Br(}qLJ}PP%-f0NMUfQ8Cs1dySCck6 zKA-dmBX6GBc{)puW@`uqyXK36u5R#DbYmJQB!va$t1u+=`Kv3CA(Dln9ya{628oSS~~Y(x`3RbRuVQK=$e*9 z#7)_1Lc{3g7Z^l?s_@C|8d5la1qvs()})G$W*wyLi&JW;wj}6C22IL4)6rlAmVS{i zs-|d82_^x`4DSB8dpR%rTWebK|2OA-y%tg9fW`rh0~!Z34rmU=R>_t%ccob;^Uh zsLM(Ng|qYBsZ=~!L=K6`6}eP#ct`Gz1$>cW@*}Mxs6Pfq-lC&L;c|N)pYjELDPM6A zGZ830pZ9Pc?`n&Oy(i-l(AOo3hEe!J_vQ8WjRv0t9~vHpixq`OBE%pdCRsF`=>U0d zi$-JU$R7+h6%Ad*(pa7FTG*F@cdSX*o+R9XDMGrggXdwzLY8XmE*7H5L4HwD)8`w7 zLQgu1gQRE_UgzMAP035OFhZABsch^V3=q{x;BxW$S}ONuCx zpQl{0c7y%DW0sRQStWsX6tKC#Pnxe7g)^K93Y6^ycMl10oK!Stl{s`3A*-;FUgXrr zHGn*%z*FVoAhLLrxdY(A&ll+zU7!^OdnA&;epoRPR7|v>U3@Hn9yk@vsWY((KrAH} z1FJyESWLYh$Qeq7BjHqd{thg`6bGIS=BT$8tQRg=<0w`~$R1wtZ0zz7wvQi=fsK%& z;1xXU4UeXU6-jYyq?8;}kq3U6f(v=Es~}-$BLzNU;l=s_&MF0|D?T~%Mkm6FSackW zH6HLK!pO<)0xq8lG7il*ijT#|$F69&2uG2HT{S2g3>gcM2RAq}=_4*7ijZeRN$_>e z2NDaqk0{8x1-<2`pi1`a+!aNp57D)i1)sBE|L;u3LMep{QZTC)ht~moGypEtMM8^V z_~=j^o2ZT{7MzRII9Q0%Vqhbh7+{w)0d`Q}+G5f1PE8)Z8vt!uTzSKG-BsWV?Ax?`iGMX78N2~%$Ziiu@FSuz$W4vm4xtq$Iw zUcd*Bim^eYsF+&JI{_LCAgn0X1R{elQ3J7bB2ZkS1P5dRzKH1R^`o6wAF_^D3^LUl zCwGHY88d&T~kA#)mg{aL#9oE7N@V?~de@lbE(Gv>z z&;`5*__ycb$?(m{tWmY%@U|^6ngr`Uhl#nP>djHO27``}syB(4bTsJ;@lF{5uJ_>f zS5Se8#!mPW(Jk)gI`<|3^$3u^!Jd94(;7#U$FAPV`>FDsVE1Dh^A8R5@2*bm^WE`Gv20#UcTsobc93F0TA-^=k z&>Zs3PK8Y;(EXpp_cvr>)~iMB9+F!&qVzd7N3Wb+CdjZRr$h z5m1{K$I%=n8w1!&E)&xKpW-F_ERA!xgOVYlD!?e?|} zc+oyy*xf6(^a3XTmRsBJYy17Aw7#6^E5cdD;FTkol z;*;hNuz-_<;&|Su=xHi~G=G2vnhm?&D>lD7nm<7K?rL7oq?$j#IcUZZlZs)#gy=w8 zU(FxjoPAxY#_nQi!{Tw}h9nA8qxl1zVa<=Yr1=9Z=-pcL2YA75y)=J-b5~LHYyJRd z*AEucwnWeiqD}7Ki$6fv|6g^1p8W(afr~=TAHdvvAqpH5{S*|#YA%N)%^$#Q{^vD+ z0JD$fB9Dqfzy)UsaJfnI2Qc$}Bh4Q`?iNb(2T-81D~@eMM+KTcfEisPD>rfO0-H|bVGnhn988!!d>mj z!!n>u^9P{5X^@9Y#V}5ZvZVO~D0G7^Ps3^c0A^H9i1zGNeq z|2GB_v0MjseTncmIAoqE61PThLgkGHV%TBbf{D@|eBS{K_AcDK3&s>(cm)oxGG}JS z9E}H$hsDN^fzL-@JUl$?2J68Mvi0C(3VZ|m5 z5@73kzIx@H3Wdo~>==d1ons%2@+VSg@eE4FqsbW9_;xqIiK4qe7wnN^i>`|Eb-+26 zojl=7j``DpW8lflCmRw6^eEWnMtb5VGh!N=mNeTp~z-viPp?@pK9~wOWgeXs(KxZ0x8SPJ_nSfEa$qUJK~rY?a$3nDBk zo?y)itWWu1TXHhGK;o;SX#UrTm(W0ilW`t~+X+4a22>WNZzI1r=>&1~u^{p?ugcO3 zYYUZc4%q+KIKYq4W;h=c{LWmysUD3LFwxGZosJ8sIxZf80X{YVx~U7MWC7$(c@F_C z`M}BP>~111$I44d$h>;(y`Wb3zwKRnXk1r%zmn{$=SZ8xwk+AQ#^X44V$WE9C~>rP zv$CYvawJ>PNKTqes@|EoBVFsxz2kdl^vEX7&Nc-4p!BgUEtFj-l$I^KTM7$XN((9U zkEYOth5oTyLZP&2C=}YV|17jif8ROxaqej3Snk-zbgvCUy65$s?>xW9`F#Q=cu0_( zps(IVEF{Ctv|2y^psXQJg4?*E8@4rTm24Rsw#XJt$Aa!kx%!A?WUE?XommBBGh_*Z z+iQ-2vy_oD2Neumo28S5SjEyu=^>bH9&{NIDHLm7!nQA=$!SO1l+;_lX}Nda>1|7c zc0IFLLrA%@6k(bpZXiaLYn_)d?XH=2o}^}e&7RUsoh%7b_Jk-Y64pbM0J*o%*;{l8 zuQ)hGai(Xk;)R^aEIGMUGnMVblLs0IkuWR`6wp=2yNSss<_)7l^vGDbV2hmoOCJD% zfN2NzZ&^29jDSGO!#m0#|37z6v#YlpqV&9`RS`N^$`uoY%)-%3tLjDavqTJBNmG@- zdz^Ri+G*cQAUacXNv@FY2Yo9^yWdV{?kc87Z@I{i@w(kP* zsBf-*=VdBeh=zI1kh0#W?VDOz2OOAf)>yoBNz(w7Y}(E`-O~tPk^~w_lq^WnchFco zybI#}TtSF}Mg49~cjZ_UsQs)C_YI@EEo<}%P{}Ch3$`K0gM{(GF08{bO%@B_r8{LB zl00ar{~&-n#)fVr5_thb#g??`C}8?XACs)aX;~|i1Cg91;kSJoK4!KYz2~j`9W>7U zhMFFWkpItE1%2Y-Dft%llILWXnKs-CX%3{V41t!W+<0W1n8E7`8C#RU07k;>9CNXg zc5iB=XU*HfDPT~2HQ8EhfBx%{A zYsutp;imXN^QlGW=Y#TML3hdq^Gs~nusjeOFmJ7bQPEm4P;6B$%41Ig;Jdme$}5Sfq_=YE82&UCw)?kO~=#BVfTTytg))x2lvW z8PKt$x$AC*p5c~Ed-HLiMe49{c1Yf}8U{zECug`?_-~RY2;q05vP?Sp&7r&Fk`P%0xp{i7w%)Kt#MgZ5Lqsk>gp)2q>G6 z0SW$CJe;HOvyMT=hXt*=Cgb!88<#T|ynT>Bts1*u)bq8~GvUi&_V+}^b{L9W_`L+T z3_J&4wI;^TUkE?j6}*oJv|3vDRI5(d`8&BBgNDfkaK%>vxq&z2L_nC?(M$F&`H_^% zH7!)toK?L#p>OG7MVp#qp?i*FI|41WYUwiSuhgnx&Y}*(ec7;pv|$v4o|~Gr3Mq@c z#wK3OjD-c@nqzLitvdx40dS%zI48%Q$>kRHitXldTG@8fu6tqZ!ufPTbMm&8F4=aq z0=-)`m&c$adyNlI}IcTV5X&6V+$X}zS?%xZ)* z@g0y~)4hFL?~5!_R8f6XY>F`^o;0Bul z5@1IyH+j6|<*+2kA0G_ydId5)HR$->d*T}#p zbiY|u{vqL)WY7MEGUtTD;mpL%<@3*vji(Yl$>dvS>1PV;B1d~%AvlPho0>?z>80@< z)I%G@_Y^zT_-Le-*g-_M3QF0zt>+Cu9e>s_nBx02om^tW{OeXh#|dj&sNbrYW}@d^ zR^2<3*7nrGGQ|H3r25tyX~jLUQo&Vz7ac>m4h0bl+ii^Z4?J*s)D+|W$9Vr{)m&q2WPKwF!N6d9`qDJPe!Kw1Dq1`ggB?>_={+Y+wDc>n%I?A`%fJZnOX z_YZH&@PYCUu`FEE_Y|jTO=Cfa*QdR>Oo+|Lc>m1*Rb)ww_s;^nYfW~c2;P4q)<5L`b1Aw8c}k%qgR;xz zigwlVuZ|CV%+OvD6{m<<#jq3Uby@lPc+RNK1 zLo#B#f8hWT*@BHJ#`_l;LJqbu-hX)8i0}p=`+93v^j;3zMp7ibk&toH#CZQP-hYhu zABaFP-ai@qAVP?8A)um3a`pocNZ6(tC=ejl#1Icqcn7$CjQ1~^+^faQNUaJn%q__a8dIHRn+4pLFlVNYR`oLa}Ml8L&r3TOY0<^HYxZ--z`O z`TvpttRLh3i7wx(l*dB@b5iObpLqZ zHwQKbmIq!KINbfM{*U^<-Ty27cK<8=7y5@1pC&#`)Dmwbp6&b3zQ6DLjlR2muk>B& zd!qM~-oNPmo!*F(>q^(ju8z)6 zI=|QX=bc~ge802Qd86}U=i$zF^;7kG>UY%NQ@^aPt2fk)dRXn)|F8T1cK;vm|F!+) z{WtbMyT5nezwP^*ec#yk%lq!^o85PIUw_AcbbP<#I~`x`sCB&7ak*o#{lD73-~P?^ zue9H7f3y9i_LJ?2wjZ^9-1gUP-){TuwlB85(Kg;Tu=77OA3Og&{Y6!Ip{-jbG#IVo z8hKNvck_h2eaEeI{owGO@&Ep_ffH}5$~bb(0|IzTbBX~R2r}7zrqOLxNmEt3WjM5@ zDo5J7RM#l#dChs*FF3rZDkt#0;@HJnp?b|Rib2|e4OJOLnn_@r!Pi4IUXzIkwRmzG zd_P!Kl_BI_V`0jJ&x5Y2jNo$-!G{q~OsL1<^#I>kGfX!qaQLpOj8Xy3UCZ0(PmnTP z;j|V)eg$arkH8e;Dg61 zarG)8nnr3FSyPo~{Z?FEa|&x>`J=0`Gx*qcBs7f2W_3ANjRSlux6O)!z8uqC6daL&yMp zS))MVzl8>l{+!Tx4PdH~AsKx=QXHviAk+%QkH5wzHk&f6c$yZMm}TU)&;J|!e8*KJUGvH zBL}ltcZ1J|=lJG=SD|*z0n|f~GWZJL2iOdEH&%m$!#8*lK%whS2`~PGl)>5P))6Ee zzD`B_J*D7=tsJ<*3d-msRCBm{JJvs)MQy&hUO{KpC!vC5ERti|K_O`bP^k zC~|a)Ppz_M86}=(TQB*H8M;bs`LwN7%Vv-?Jjp99Y2YcQ1AYW)PkupFo&t%kQ@G?; zb?_xlTcwsajqvl4pXDpp1A+u;wiT2~UQv~EXx>Xqn|5J6n&Z&V(7Av;dvj*V@a$z>@foV_cW!h+M>!RQM;5a6g(ycDe zOis_wWXeT9;m{>aL#0bCIqdQfd_Qs#48wP=Vx*^O4Hbcq&cLy@P_s>6e>V1ExoTKZ62W8!k?;o7|;9GykzN1a=yZ`x62S4k@ z>|>|auN-X0_h@$d{LC3u`8-HiO1o=@Q%x3i7vq*JYY2xVj>zffROO|e`AYhZoadia zl~<87YnQ5oIi8$!3Ts9cDB3mr(R7erJgq7kionzQ&gC?Xb9xS^Uz*<|(l7h*5z<#p zpd&`;x_nAiR!~%&98?XOW3z)z6UJ7YTN!a?Jok(^A1|dbt9GA{C&l@QyknSnVw3kh zA5T1ui)eSZdOJ%Ssf)D<9V|i>vkBW`@tbT zziE}N)$;!5#8;H#w3%i$T&x^k^}vTpVjlfu)9c)zssw*n!Bpee)W+M~E5S7_T6auH z7&_Fr#RW+t2l+uyG-v@veURM$FG_j_wD4)&ys3c5lTWG2iy+e5q#7XgpYW+U_arCZ z%Z6ps9IXFyeu2R!=p^k@J$QbX_8Hc%!O!^#g&IP`ZwCpf0advON=&V071pxhrP;Rn z{lY{2#1zaCh#nMwTMz3!k>L08W}yqZgYtcxsaOkMgn*#=puT2HPkR3m8i23$zTdmjJJFl$RiOv?sOL|5e!XYC=SI&{-9PF67}dxBVh+R{ zh&d2*Am%{KftUj^2OgLMr|S^Kue38Mcx#)k=M5pclyBg2_rX~2m;d2d9n$z2e%%(s zd(r*z1Cr{WtV5y>#h$}=zVy5Ak6fxlR$k@}kO3lVn>7~u*%t*wbBFT#{!Q{&9fC3` z-WQneX_0C9Ag<2)8IpBK$E0Y2gVP2CRCpFqwPKdhI>cTwns`}uRx((J%qtoPg6fad zA>^J!XN%hmiIHMzg^eGnL#`#AIl6*K#t=Nv?wn8BU>zbY)mmNCnOa*&fmBN=u32Li zfFLDRha^k#j>}`Mu_qOzj6}sZ{EAa`$g`A*qzCl3X{N#Y(P*E7;z#R8xSUY{zgBIB zlN}_F)*1*g`RyOAL);}p1af4#ok>hSRX@x%2+<)SJqSQ%#hl4H z&mfu#Y4vClg8f5VT2cVuH(}_A{UuHYgt=cSf72;$Ha*fsx@Q%$R*Dg6A z_fpqM0n{|dU>zc_I8%b!pQ%H(C1n;wMc=|ERT4!E^C@~uny^0 zY%QqdSRFDit&2r{6}lFOYYOhT8-6RPIwW7>8$CFIf>Nx%=4TqLL-G~t4^ocTA^4I- z?K-paiKVMy>7HomK>j;Xhf0ygqgn5QT*vDWhpCMv(xr$^Y&m`#&($Fllj1gu7=VT9 zZOt)u&-`>9A~G3T7YrS~I!?8Dor84<%3`mB)>3uI$;7m2ZmSf_2boUQq2#=ROfcux z%GNy^O4XtEr0S+LYeRFz+QJ?V)geEV9=57h-FV!kga7%C)0-lGgW+~v{GCL)=rH}v} zFO0jbYI=|FgnXB4xei(_d?&S+DNoJHf;FVJ7ugBMvF%$m{(J2|F1ZGxlzR$&2`ir% zAt%PW2V24jD4T%=P8JW!rau<&BalS|NfB}zmopc8;|D)S<)j%YDNBlgWNAR(*)kG6L& z!CrJXEyg2(Pv~0$jY3%Gbl5w=pjpSFaTQ1fqxgNC?a2_*%zsWipWw48vv88!CTpWu~%_ zK`R90_bB+bXY%er7Z$4T354avHBsR=G36F1 zn0$C3c@YoZKP)+#A&A#I^W!Fh`=Sj(9+>TJbJaIDb#%DA*VEmuyM2SbiO>ETSqo znZ3q1Ok6yUU)j~_Y;Q>!OfkR85h`q5ReUIMvWZLNL{rt=@`{@JiowJOt7a7ji;E{I zEGB2G+rPSNWhg~toQaD9SiIiHhh%zIbPl_L9;?i&B)&UaX6qCR440CR%ZuCAV1Q?Rg)1Yd^Kfy zv(Fx?KQ_X|CF891F7JAGv&$z8M%Y6U&0StRuY(c#{F;=|pm=IxLa*Cu2FLy3nwTkU zAmVMTOLbmPtGB7$*?hkI7@mz$SyS^`S4Ru3R=6Vm#?R41@xrKHmOI(PdL2xHb9Z_@ zYX%#VWHxb`WKdi!ZokLd?CDtLZXJwGHJP|P9NW~{>0`?1bFT4uItCNO8;1_}V3gip zn;GiYFKV-TS<@l_o<1_G>wTd?vf`1?w|yYMZA!C}2oEWX;I~SqEJ&Y7kHe#I7rY$S z!VU66%6cUqw!$wIs{&*se<{Cd`#||Z{v-SpmPpq?QGQCkToP@6Q9f1Pg>lNG3X&RO zp;Ri3kxS)`hZio`4h|PM{v<{zLK+~wD5QNUOc08J{?Xh~Y0gAp8mO;mtn##a8kekg z`(2F-E6W-Sot+)6c_dCRm=}Avq~S1##U;2qT3j2QtNrb5Nfsdnw0N3*iMn-pvcW7w z0X=8=e1k)%0D56{5{TB(@+a*!ArS;;K_KsXW8>9JB_SEKH@Q3Ty!i4-PRzL`Axgvp zWQAwBeC0D9{u#auJD?l3z(#l(EQEi9H^8f5FYJascnSdn0dK>1Gj8qR@b@DeylIfE^Qrlc4J0E9wLL-2_Ft@OOKNAkdv5W!sdCG3#9lsZL#4RE3S8~K#nARm?Qvh^r$%ZF_@ z!D4BKl6*#1r za1L_wlMKbULm$nJ9qmjuOam8Fh{QY^i&Y}-@VU*$K>{?Sap6iK8e+JhR{Um5szEeh zt@vR}y)oTTfy>8gVdSH6U3%&982yGTyL3x$Znk7d!^cGm~Xj%aNKJ}Bm87Zx{In`J8VFb32G!ailue)15w`1c7L|}>}l4#4>{Z2c!ibN7cBoU%v#|b-R5}8W) z=YH_o6(*60#IDWBSX5<~naGAkQ7^p}(Ow@RVF_+htN}NPh*In9*jSP##Tr5qVqUE9 z1rDBqufi8_|4ze?;XCkm_$xX$kX8qF!~Qy({=$*z)#mkFhH(jpqo0F2V7+v+)NFoV zK8@|lmGU&%VzWuVRK8U1P!^eG(@s;2agX^yDam%y<})ra_gEjXUT&4d$HYaJ?=1m~ z^KhCSe+CuWG=1aA3c;sM((ie(i`ORVsV}L#HbLM2(mGxnua7#mN;Ln#nK;p@)##5L zi`MmHNnkR5b7mxIQrk}O5oY-L=bUi5OFP^Vq07rwkuT5RLQ%D@;r zv_!#PP1YZHc_CP&|M>C}P_Hj}r4cOD2VPkM7U=NR8c?S%e|3?q7FST|7Q=ElO_56E z1kI`Ey*5#J4%g8CTAr{>o2vJ{b~z~4|NL4Nn4%XSpT%dj>&BO}_`EiK%8PjxMd6HM zxt6bge7syJ(DL-{FF1`wF(q2A{>ZONc`Zl(>Q_^QTrFGw9pGirvLLpzV(bbH%3=3Vpt~P(Eue+leJdq;I z;@k!wE7`)4C^tybVo(`X@+U4^#wYtD#p#+n`VMR#g7rA`Ftk1*<`JmkEYVy10 zczph{E_Yjt%bNj7s(QSbvkKnPYu`^_{I*@l;G3H9*21^QgI9X+R_PM;^4M|AkS2p=vi@j~&btt6qjcuM*cSl{5e>FHoN{&5AS{+m> zXFcv8*`|OK`lN|Arp{VaUoup-#53V zJxa&{i<-QxF8^%2Z*k!^u5BY9V>#VqkbbhaF0TtbI7-Mr9}I1zzypy&=AgKV?wfn> zC%vloH+lVCo#4Lkz`Z08>uGDl19T`}n8-H11sWn(ef(HQ!-{m0Sko4R9a4lNcXt zic0a?_6qzZUbY{D55oV1AL51l4VVIBp&g2lhg0ErxE^}oYS@Gq{(4vi$3XL~@FsW- z?8SQdn9^$!055|l7(LGDF-C_OJxVAF3=opQJ%l2`Nk%8gI&8~;2RUOTlf1*|ZANb~ zdXv!`j9zDS3LZ2Gy`<=8h#(3)&FCpcPm-c7?G(wZo1`ofA%O=OJ;3OGM)xtg7pKFC zWN?VlBa9wq^bl=rI>j`Kj!TWWXahWrkxK{;>S<+#k}m&EJ}j@7YvgF@kJ95(we2(8 zYFn1|c58vyZ8>5oH19TNn)aKDjSm>d8u|=T!tKH+KERv7ZXj`6`}?yE0gGCue}8r= zC_<$_2Px>pJ@`Cu#TQwkT582h45!MdbSD_kqQ~pseBlt)5*iaI4U1tJ?VVmvr_ZoK zoyk%(g{6qqKRg$!|JRpxUY&uS-vY+zk9-lyijC9jzM9Fa)AjzZg6&|5|Mpd^s9wT~ zY93Zp&pBMwG_?025SA&MSEr)aZwW7*mDTli4zCuYJ^t|2ak}(P0VJpTo2cLT-_fEvktJO=q_K%Q{Hxh&S0~VDH3~&+1{GF( z2zGfpy>6dN@A&I9!K#i&58MI9p}jYQ(czKc+lkgmY7xuZI4tkY->$F)#;b)ae%T1| zmGM>X^{&PEL{6*(K5IMKJh{{Y{flo~c{N|Z>~A+Ks#7F0-p+AAu#}-!H-c>4@tsMy zQq4ojw}7g!Hlc_fkgo6j&Md0AtjiO_yNn*$1w=7aNe-@L6sp?^Mu(<*#rKgVPBoiW zSI==Gu8tk;8baLWX>MwBUT_-AQL|`KH2O4T@@hm;%SBqr;2SfBQp%qGnJL9xT#&UHE%}qNY=k z8y~-ksPymC6*Y~DT-=zTC`#Y+_pyrVpyFl0%x@A=DizHSip)Qz#7t0AsO$rea`Q5=9lc_xt$8B`L+79?Ja!5F7*#F(fq#~7=Y zJqCcoBt5`wmm-nb0nX(hsZY9IQl-t3Uuu_DNsZD{X@N9PDwi&iCQ42zQ*uc0QlxZ1 zx(nOrKU=Adwg774EZ|;Z%Ph!FQYw-?qal?(Jn@J zGTO=L4pT3!;&v89gkrfqM%!^0jTRPj8>1bJZe^r1x`k0cBbwO)wzJU9jBa9dBcmG_ zZ6nlc0oSwOb&RfMbPc1c8C}IlW27<)Fxtu}IFMJe&=y8Lj5agc#HgFmMoPV40}HNa z)Wyip$j8XbXdRo- z$!IpC3P!USl`|@1R2tO35*D1vXa=L{j4oj`jnPy_#f+vfn#^btqlt_rFdEOOh*2S< z0!I0Ck75B%7R+Om%P5CYHlr*?;}~T!8p~)5qtT2q7^O2xW8`3z$|%JuPr)YRZcZ-Z z8~ zJ+@w>!13TdiuY2yhvGqsKc{$r;?F4Vr+7ETeH8an+(Yp$in}T9qIf68ofPk&csoTz z@it>GseT6y+)9w^qe#pKcHZDPo#HJN`zg{CU^{)knc__pZ=`qw#cdR?r+6L3Ybjns z@oI`!5$pvT4X6|Y6t_}jBXcEv-$Jp6;%17QD0WlaNO1$j^%T1(`YHM-dMU1>*h$et zvA2T~-o@g+wozP5aScT`#nlvBDXyaEqS!*Qnc_-{O%zv9Y^1oH;uRDdC|*wSGK$Ms zFPGB55{j2nTugBh#d?YhDK4N`N3oV-4aI7TRTSq_oJVmk#W@r!DbA)?L2(wF|8g2A zqgYC@gyKw!Gbm1{cnQU66sJ-wrZ|P-WQvn0PNX=2;&_Th6tP7Lou6T7R7NCGbxUxIELbAiWwBsDW*|$P)wzmLXHpseut4uhTmDc#J9u_F%^j1 zlU)BTyZPEUlx^ngl#{DsZFm>Bc+AyzRdQnnJSD&e26PKvy`M&0*GO+ksW#1e+!`;sEW6B~nIlbQ z#y-PmhB5;XI`|Lyjo>q|j{A~xq0+q|TM*TaBe)x)(6%lxhF3SBLtWt>iX@b}9zb4Q zj}Gk%mnWj#>w##ssa@>YFAhESqvv};DoWk}VtLh158#f?z=-bY0~66T8^9>+Zt#uh zZeST{5~zAn?ncn3sO#vda@~2)z<41;?L=um8}62P8< zCiai|41o;QbCFzofCE+D3=+`xZV)Xv)edCcJj~}%f~IW(@zyG}opxKZ4eNHq9x(Ru zpnKCXyJ@A@-RxN8@wE9Gs@=_AkI%Ep@4VFQ>uPGN_jk3pJRL8w3x*elTR(kv(^^+}a~I&oVs|y| zg)`*Ap^45nutHtK%0wUC2-1hTkjR{rBwV~4^u;Eu5e2Fn$y)_ice{JmS&h2inL(4HBMc{;xmTz{8$etw-%}{7Qc8{Jm~?tdkaVsBGne+ z;R|<1VgK0#X;8-;YBSn$-AJ0b2V|l*t^}h+btSDQP*3WKW?#jeUXW&uQJYu`l83bb ze^4`pE7TR}rarJ-;MGRrOdRH|qn}SLR{yra$st>gWNtgQ8Tih=Nab?~$F4 z&K>~Kq82?os*%^CkaR=HYE+}_gCJJaB3a6uFn?V&dhH+>#cL7hS3AP}pv2u99~l}~ zw`QkV0~KLesoyt(*C6`n9$Hh4@8NYjn!TmR(mx1{r$jh?@!h9Pe2SiR?* zI2hlp2`KsD3(LOdVGto|JnLh~^NwB7$x-;$ikSxHZw(kU5Z+?6w-b!#HEw8)XvR7a z$*aA@wHxM(XFYso9a%T7Bnw2ClRFko_ks*j-NIVY8#WUx8;-W1H@zfp&q$+y7W)A9 zw{J%4d>5Ac8z0Ey)lDOK?i0~^Kgi_O?jf%GL?m^Am?H9R#R%OTT&@f#7Q7lCkt%KX z*?8-n)^TE&<%DI0`CW63>0Xn?=r$ZRBn#dB{o@S*F|hXHi*R7g5LF2-!U6Y17U4k9 zGXB&e9B3VJ5e}^S2aB)*13{Y@5pZbP#IOZtBo3Xr4%G5m7D~JR0+}6Mbv>9Nl52Hx zfipd9nrI$7%G^di(oEF8?R>_g+rT_t8yjXZ;t-ZiLOX6CwqXorDyxv1`6Bf8cHBhob})|DQqZpLpv4v#ttGQ!rVX?AcqcLYyv2&wl32nq z7c~CaJz&P*ciW{UhG|F~!jX|^)ZHM$nyDqQ+@&K`<3M}v2IEC7o~6kQtDzPx-wz^1 zEsjNnkKBCp*Zug*&|=9@1$AORI`}h?Dr%!x^8B!p=A)VeAg+XbFiBh+hku54Mk$pK z%G0nbZl3K^+j8sM)@t#HSZLX2i8J?`MN_x&V`GisDST_##(&CJgPkCbYwPdNwFSnh z%UK2GBXwsi`b$5^6?)Yxupu9LfsCoCSQNa33goK|tgsPgvIi9CFMJ!3G4%c_WJv>2 z>g6o+@QoSW09WWBRWPWR5sNr-Q&4UXP>f_}y6h)(PTYZ~vg=m7{YY1r-qwA=?gL>> zaUh%`Pl!;Lkd-8SZ$dT%F=+B_AcE}1E$G=DK*3jmm$GILy9yjkKGqtgF8;~By>%Pz zo1`ux>(E8|Mrw>IbFIQZ5FOl(1Pp5ZPYlPm2t@GeLX^Kdq*Tndcij$>c>J}U|K^$e z``bYZuhtD)46nX}oM&o>Eg>;GK?bkZ43Q_IgF8VguU3aIUF60X72b&#TeWIfy-(dq z>YYDqS(v>Gn=5r5TE1(r{p30_QdH;C(Y)Z=I!<5ly>#C02tOGR}Si%uJwf0os!mb1FU zFPE8((f@Q-G2rid911|bVW8y{*aeZ}6<}x}Upp|r$KgNnV{7sh;3q%$vrCa zIxB${O>5?*fuk$=UHm`FsJZx36#qF$x@h4=D0vk>6aC@&pG@=kD!u|;^VUzK=_2jx z95Afr-!zjk8IAT`%O{{mzX4U~XeVDd;O*pHw9jMEI+d?O_FmpLFlj5lj|#`4V`unc zw6~96HqhS3uc5+B)U<|oqP=_hQ3I)a`6sE6LqOx_4vc<;Umzwlq?b=^Xc%$edW!K+ zwaU-~#X<^tajFoFI-cUq=*(06HTd4Xf0_`Fwm;2pVejRr?iqd_d+!g4I-lhihmwBq zEPr*_dm(!GIezIt@h@-+>>-XsdynwVAPepLHHaf>@F7I@3Sc1Pkd693!P6eng?Dhw zaTb$<8qWX+(S`S*rNif}!>M!8?>6!a(ALvn`oPau@J0Vxn(>L5e8G7I4Gs15|0d9( zZ$R~+c68C{b)taEmkeshAxJ#^`7LO{Rs4E%rXTAJR*y|IX#rZdhEEw(kC%h$5ux$L z1JMP-;{Tm`7}4osK?_ax|5Zm2))7BCJ41*-kIfL?2`P&a?I)r=Q!u=EgwG$h(ADO` kzxnGa?dZlg3S^kbRR;b=YlZSv`0Yl2|6Tu&mmBW?0VCC&o&W#< diff --git a/Backend/Backend/Backend.csproj b/Backend/Backend/Backend.csproj new file mode 100644 index 00000000..0c062427 --- /dev/null +++ b/Backend/Backend/Backend.csproj @@ -0,0 +1,20 @@ + + + + net5.0 + 87db58ea-202e-4b41-8dc7-1fe430479a63 + + + + + + + + + + + Always + + + + diff --git a/backend/Backend/Backend.csproj b/backend/Backend/Backend.csproj index 56a640b0..0c062427 100644 --- a/backend/Backend/Backend.csproj +++ b/backend/Backend/Backend.csproj @@ -6,6 +6,7 @@ + diff --git a/backend/Backend/Controllers/SimaProController.cs b/backend/Backend/Controllers/SimaProController.cs index b4b06590..12859ad9 100644 --- a/backend/Backend/Controllers/SimaProController.cs +++ b/backend/Backend/Controllers/SimaProController.cs @@ -10,7 +10,7 @@ using Microsoft.Extensions.Primitives; namespace Backend.Controllers -{ +{ [Route("api/[controller]")] [ApiController] public class SimaProController : ControllerBase diff --git a/backend/Backend/ProxyMiddleware/ProxyServerMiddleware.cs b/backend/Backend/ProxyMiddleware/ProxyServerMiddleware.cs new file mode 100644 index 00000000..0c4a0e55 --- /dev/null +++ b/backend/Backend/ProxyMiddleware/ProxyServerMiddleware.cs @@ -0,0 +1,60 @@ +using Microsoft.AspNetCore.Http; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Threading.Tasks; + +namespace Backend.ProxyMiddleware +{ + public class ProxyServerMiddleware + { + private readonly RequestDelegate _next; + + public ProxyServerMiddleware(RequestDelegate next) + { + _next = next; + } + + public async Task Invoke(HttpContext context) + { + var endRequest = false; + if (context.Request.Path.Value.Equals("/proxy", StringComparison.OrdinalIgnoreCase)) + { + const string key = "url"; + if (context.Request.Query.ContainsKey(key)) + { + var url = context.Request.Query[key][0]; + await ProjectReqAsync(context, url); + endRequest = true; + } + } + if (!endRequest) + { + await _next(context); + } + } + + private static async Task ProjectReqAsync(HttpContext context, string url) + { + var httpClientHandler = new HttpClientHandler { + AllowAutoRedirect = false + }; + var webRequest = new HttpClient(httpClientHandler); + var localResponse = context.Response; + try + { + using (var remoteStream = await webRequest.GetAsync(url)) + { + localResponse.Clear(); + localResponse.ContentType = "api/Projects"; + localResponse.Headers.Add(); + } + catch (Exception e) + { + // Do some logging here + } + } + } +} diff --git a/backend/Backend/Startup.cs b/backend/Backend/Startup.cs index 081cd9a5..3d7e98e8 100644 --- a/backend/Backend/Startup.cs +++ b/backend/Backend/Startup.cs @@ -1,3 +1,4 @@ +using Backend.ProxyMiddleware; using Backend.Security; using Backend.Services; using Microsoft.AspNetCore.Builder; @@ -22,7 +23,6 @@ public Startup(IConfiguration configuration) { Configuration = configuration; } - public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. @@ -30,15 +30,13 @@ public void ConfigureServices(IServiceCollection services) { services.AddControllers(); - services.AddSwaggerGen(c => - { + services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "Backend", Version = "v1" }); }); services.AddTransient(); services.AddHttpClient( - client => - { + client => { var baseUrl = Environment.GetEnvironmentVariable("BaseUrl") ?? Configuration["BaseUrl"]; client.BaseAddress = new Uri(baseUrl); //client.Timeout = TimeSpan.FromSeconds(30); @@ -54,6 +52,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) app.UseDeveloperExceptionPage(); app.UseSwagger(); app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Backend v1")); + app.UseProxyServer(); } app.UseHttpsRedirection(); @@ -62,10 +61,17 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) app.UseAuthorization(); - app.UseEndpoints(endpoints => - { + app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); } } -} + + public static class ProxyServerMiddlewareExtension + { + public static IApplicationBuilder UseProxyServer(this IApplicationBuilder builder) + { + return builder.Use(next => new ProxyServerMiddleware(next).Invoke); + } + } +} \ No newline at end of file From f56c6d642ccb8f5bb82cabb9621b62698157f591 Mon Sep 17 00:00:00 2001 From: SaiVarunVaranasi Date: Tue, 18 May 2021 19:01:41 +0200 Subject: [PATCH 02/32] Proxy Implementation --- .vs/amos-ss2021-carbon-footprint/v16/.suo | Bin 43008 -> 43008 bytes .vs/slnx.sqlite | Bin 212992 -> 864256 bytes backend/Backend/.editorconfig | 3 + .../Backend/Controllers/SimaProController.cs | 13 + .../Backend/Properties/launchSettings.json | 14 +- .../ProxyMiddleware/AspNetCore.Proxy.csproj | 24 ++ .../ProxyMiddleware/Builders/HttpProxy.cs | 141 ++++++++++ .../ProxyMiddleware/Endpoints/RoundRobin.cs | 26 ++ .../ProxyMiddleware/Extensions/Http.cs | 185 +++++++++++++ .../ProxyMiddleware/Helpers/Helpers.cs | 116 ++++++++ .../Options/HttpProxyOptions.cs | 254 ++++++++++++++++++ .../ProxyMiddleware/ProxyServerMiddleware.cs | 60 ----- backend/Backend/Startup.cs | 12 +- 13 files changed, 771 insertions(+), 77 deletions(-) create mode 100644 backend/Backend/ProxyMiddleware/AspNetCore.Proxy.csproj create mode 100644 backend/Backend/ProxyMiddleware/Builders/HttpProxy.cs create mode 100644 backend/Backend/ProxyMiddleware/Endpoints/RoundRobin.cs create mode 100644 backend/Backend/ProxyMiddleware/Extensions/Http.cs create mode 100644 backend/Backend/ProxyMiddleware/Helpers/Helpers.cs create mode 100644 backend/Backend/ProxyMiddleware/Options/HttpProxyOptions.cs delete mode 100644 backend/Backend/ProxyMiddleware/ProxyServerMiddleware.cs diff --git a/.vs/amos-ss2021-carbon-footprint/v16/.suo b/.vs/amos-ss2021-carbon-footprint/v16/.suo index b614cf18dd172418b780cea72c31604d624fd3c4..bb048947aa8ca53b7607b363db0aea8bc4821939 100644 GIT binary patch delta 176 zcmZp;z|?SoX+sVZTLIsll|Q{V7cu=}W;;;+8q8+nlM_h(alZM~y`8_!ic^0_sRt%* zo}jXU14DFifUdLLQrWNjV=4`udZPGN&eYlsW}holEy!)>I}lU3Ijer#-oOF?J!?yb delta 176 zcmZp;z|?SoX+sVZo5GZT;=x{=LVD`B()dD_yzPRqZ&3OgUTq;Q^sYXeO vrm4Ed7KW+1Cgw(#x)v#EX}U?qX=%wuMiyq4X$G6$Rt0NdSg|=^@dg$EwL3)4 diff --git a/.vs/slnx.sqlite b/.vs/slnx.sqlite index fb057e47f2e992330fe0f1dd8325ee4f1de26dd2..76fa01ffb77ed64f8fe41f4374b1cacfcf40d354 100644 GIT binary patch literal 864256 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 z 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 z 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 QX)Punt;cF7JVv4a0njO^^Z)<= diff --git a/backend/Backend/.editorconfig b/backend/Backend/.editorconfig index 47fcc1c6..1965d4f0 100644 --- a/backend/Backend/.editorconfig +++ b/backend/Backend/.editorconfig @@ -90,3 +90,6 @@ csharp_preferred_modifier_order = public,private,protected,readonly,async,static dotnet_style_qualification_for_field = false:suggestion #prefer properties not to be prefaced with this. or Me. in Visual Basic dotnet_style_qualification_for_property = false:suggestion + +# CS0436: Type conflicts with imported type +dotnet_diagnostic.CS0436.severity = silent diff --git a/backend/Backend/Controllers/SimaProController.cs b/backend/Backend/Controllers/SimaProController.cs index 12859ad9..0677240a 100644 --- a/backend/Backend/Controllers/SimaProController.cs +++ b/backend/Backend/Controllers/SimaProController.cs @@ -8,6 +8,8 @@ using Backend.Services; using System.Net.Http; using Microsoft.Extensions.Primitives; +using AspNetCore.Proxy.Options; +using AspNetCore.Proxy; namespace Backend.Controllers { @@ -56,5 +58,16 @@ public async Task ExecuteResultAsync(ActionContext context) } } } + + [Route("{**rest}")] + public Task ProxyCatchAll(string rest) + { + // If you don't need the query string, then you can remove this. + var queryString = this.Request.QueryString.Value; + return this.HttpProxyAsync($"{rest}{queryString}", HttpProxyOptions); + } } + + + } diff --git a/backend/Backend/Properties/launchSettings.json b/backend/Backend/Properties/launchSettings.json index 45d18566..126e6f23 100644 --- a/backend/Backend/Properties/launchSettings.json +++ b/backend/Backend/Properties/launchSettings.json @@ -1,13 +1,13 @@ -{ - "$schema": "http://json.schemastore.org/launchsettings.json", +{ "iisSettings": { "windowsAuthentication": false, "anonymousAuthentication": true, "iisExpress": { "applicationUrl": "http://localhost:16294", - "sslPort": 44323 + "sslPort": 0 } }, + "$schema": "http://json.schemastore.org/launchsettings.json", "profiles": { "IIS Express": { "commandName": "IISExpress", @@ -19,13 +19,13 @@ }, "Backend": { "commandName": "Project", - "dotnetRunMessages": "true", "launchBrowser": true, "launchUrl": "swagger", - "applicationUrl": "https://localhost:5001;http://localhost:5000", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" - } + }, + "dotnetRunMessages": "true", + "applicationUrl": "https://localhost:5001;http://localhost:5000" } } -} +} \ No newline at end of file diff --git a/backend/Backend/ProxyMiddleware/AspNetCore.Proxy.csproj b/backend/Backend/ProxyMiddleware/AspNetCore.Proxy.csproj new file mode 100644 index 00000000..0236c825 --- /dev/null +++ b/backend/Backend/ProxyMiddleware/AspNetCore.Proxy.csproj @@ -0,0 +1,24 @@ + + + + AspNetCore.Proxy + AspNetCore.Proxy + 4.2.0 + https://github.com/twitchax/aspnetcore.proxy + + netcoreapp3.1;netstandard2.0;net5.0 + latest + false + true + true + Library + + + + + + + + + + diff --git a/backend/Backend/ProxyMiddleware/Builders/HttpProxy.cs b/backend/Backend/ProxyMiddleware/Builders/HttpProxy.cs new file mode 100644 index 00000000..18febbf3 --- /dev/null +++ b/backend/Backend/ProxyMiddleware/Builders/HttpProxy.cs @@ -0,0 +1,141 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using AspNetCore.Proxy.Options; +using Microsoft.AspNetCore.Http; + +namespace AspNetCore.Proxy.Builders +{ + /// + /// Interface for an HTTP proxy builder. + /// + public interface IHttpProxyBuilder : IBuilder + { + /// + /// Sets the endpoint on `this` instance that the proxy-to-build should use. + /// + /// The endpoint to set. + /// The current instance with the specified endpoint set. + IHttpProxyBuilder WithEndpoint(string endpoint); + + /// + /// Sets the endpoint on `this` instance that the proxy-to-build should use. + /// + /// The endpoint to set. This takes the form `(, ) => `. + /// The current instance with the specified endpoint set. + IHttpProxyBuilder WithEndpoint(EndpointComputerToString endpoint); + + /// + /// Sets the endpoint on `this` instance that the proxy-to-build should use. + /// + /// The endpoint to set. This takes the form `(, ) => ` + /// The current instance with the specified endpoint set. + IHttpProxyBuilder WithEndpoint(EndpointComputerToValueTask endpoint); + + /// + /// Sets the options builder on `this` instance that the proxy-to-build should use. + /// + /// The options builder to set. + /// The current instance with the specified options set. + IHttpProxyBuilder WithOptions(IHttpProxyOptionsBuilder options); + + /// + /// Sets the options builder on `this` instance that the proxy-to-build should use. + /// + /// The options builder action to set. This takes the form `() => void`. + /// The current instance with the specified options set. + IHttpProxyBuilder WithOptions(Action builderAction); + } + + /// + /// Concrete type for an HTTP proxy builder. + /// + public sealed class HttpProxyBuilder : IHttpProxyBuilder + { + private EndpointComputerToValueTask _endpointComputer; + + private IHttpProxyOptionsBuilder _optionsBuilder; + + private HttpProxyBuilder() + { + } + + /// + /// Gets a `new`, empty instance of this type. + /// + /// A `new` instance of . + public static HttpProxyBuilder Instance => new HttpProxyBuilder(); + + /// + public IHttpProxyBuilder New() + { + return Instance + .WithEndpoint(_endpointComputer) + .WithOptions(_optionsBuilder?.New()); + } + + /// + public HttpProxy Build() + { + if(_endpointComputer == null) + throw new Exception("The endpoint must be specified on this HTTP proxy builder."); + + return new HttpProxy( + _endpointComputer, + _optionsBuilder?.Build()); + } + + /// + public IHttpProxyBuilder WithEndpoint(string endpoint) => this.WithEndpoint((context, args) => new ValueTask(endpoint)); + + /// + public IHttpProxyBuilder WithEndpoint(EndpointComputerToString endpointComputer) => this.WithEndpoint((context, args) => new ValueTask(endpointComputer(context, args))); + + /// + public IHttpProxyBuilder WithEndpoint(EndpointComputerToValueTask endpointComputer) + { + _endpointComputer = endpointComputer; + return this; + } + + /// + public IHttpProxyBuilder WithOptions(IHttpProxyOptionsBuilder optionsBuilder) + { + _optionsBuilder = optionsBuilder; + return this; + } + + /// + public IHttpProxyBuilder WithOptions(Action builderAction) + { + _optionsBuilder = HttpProxyOptionsBuilder.Instance; + builderAction?.Invoke(_optionsBuilder); + + return this; + } + } + + /// + /// Concrete type for an HTTP proxy definition. + /// + public sealed class HttpProxy + { + /// + /// EndpointComputer property. + /// + /// The endpoint computer to use when proxying requests. + public EndpointComputerToValueTask EndpointComputer { get; internal set; } + + /// + /// Options property. + /// + /// The options to use when proxying requests. + public HttpProxyOptions Options { get; internal set; } + + internal HttpProxy(EndpointComputerToValueTask endpointComputer, HttpProxyOptions options) + { + EndpointComputer = endpointComputer; + Options = options; + } + } +} \ No newline at end of file diff --git a/backend/Backend/ProxyMiddleware/Endpoints/RoundRobin.cs b/backend/Backend/ProxyMiddleware/Endpoints/RoundRobin.cs new file mode 100644 index 00000000..60b54b00 --- /dev/null +++ b/backend/Backend/ProxyMiddleware/Endpoints/RoundRobin.cs @@ -0,0 +1,26 @@ +namespace AspNetCore.Proxy.Endpoints +{ + /// + /// Round robin endpoint helpers. + /// + public static class RoundRobin + { + /// + /// A helper method that "round robins" over a set of endpoints. + /// + /// The set of endpoints to "round robin" over. + /// An that "round robins" over the provided endpoints. + public static EndpointComputerToString Of(params string[] endpoints) + { + var position = 0; + + return (context, args) => + { + if(position == endpoints.Length) + position = 0; + + return endpoints[position++]; + }; + } + } +} \ No newline at end of file diff --git a/backend/Backend/ProxyMiddleware/Extensions/Http.cs b/backend/Backend/ProxyMiddleware/Extensions/Http.cs new file mode 100644 index 00000000..f2aa64c1 --- /dev/null +++ b/backend/Backend/ProxyMiddleware/Extensions/Http.cs @@ -0,0 +1,185 @@ +using System; +using System.Linq; +using System.Net.Http; +using System.Net.Sockets; +using System.Text; +using System.Threading.Tasks; +using AspNetCore.Proxy.Builders; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; + +namespace AspNetCore.Proxy +{ + internal static class HttpExtensions + { +#pragma warning disable CS0436 // Type conflicts with imported type + internal static async Task ExecuteHttpProxyOperationAsync(this HttpContext context, HttpProxy httpProxy) +#pragma warning restore CS0436 // Type conflicts with imported type + { + var uri = await context.GetEndpointFromComputerAsync(httpProxy.EndpointComputer).ConfigureAwait(false); + var options = httpProxy.Options; + + try + { + var httpClient = context.RequestServices + .GetService() + .CreateClient(options?.HttpClientName ?? Helpers.HttpProxyClientName); + + // If `true`, this proxy call has been intercepted. + if(options?.Intercept != null && await options.Intercept(context).ConfigureAwait(false)) + return; + + if(context.WebSockets.IsWebSocketRequest) + throw new InvalidOperationException("A WebSocket request cannot be routed as an HTTP proxy operation."); + + if(!uri.StartsWith("http", StringComparison.OrdinalIgnoreCase)) + { + if(httpClient.BaseAddress != null) + uri = $"{httpClient.BaseAddress}{uri}"; + else + throw new InvalidOperationException("Only forwarded addresses starting with 'http://' or 'https://' are supported for HTTP requests."); + } + + var proxiedRequest = context.CreateProxiedHttpRequest(uri, options?.ShouldAddForwardedHeaders ?? true); + + if(options?.BeforeSend != null) + await options.BeforeSend(context, proxiedRequest).ConfigureAwait(false); + var proxiedResponse = await context + .SendProxiedHttpRequestAsync(proxiedRequest, httpClient) + .ConfigureAwait(false); + + if(options?.AfterReceive != null) + await options.AfterReceive(context, proxiedResponse).ConfigureAwait(false); + await context.WriteProxiedHttpResponseAsync(proxiedResponse).ConfigureAwait(false); + } + catch (Exception e) + { + if(!context.Response.HasStarted) + { + if (options?.HandleFailure == null) + { + // If the failures are not caught, then write a generic response. + context.Response.StatusCode = 502 /* BAD GATEWAY */; + await context.Response.WriteAsync($"Request could not be proxied.\n\n{e.Message}\n\n{e.StackTrace}").ConfigureAwait(false); + return; + } + + await options.HandleFailure(context, e).ConfigureAwait(false); + } + } + } + + private static HttpRequestMessage CreateProxiedHttpRequest(this HttpContext context, string uriString, bool shouldAddForwardedHeaders) + { + var uri = new Uri(uriString); + var request = context.Request; + + var requestMessage = new HttpRequestMessage(); + var requestMethod = request.Method; + var usesStreamContent = true; // When using other content types, they specify the Content-Type header, and may also change the Content-Length. + + // Write to request content, when necessary. + if (!HttpMethods.IsGet(requestMethod) && + !HttpMethods.IsHead(requestMethod) && + !HttpMethods.IsDelete(requestMethod) && + !HttpMethods.IsTrace(requestMethod)) + { + if (request.HasFormContentType) + { + usesStreamContent = false; + requestMessage.Content = request.Form.ToHttpContent(request.ContentType); + } + else + { + requestMessage.Content = new StreamContent(request.Body); + } + } + + // Copy the request headers. + foreach (var header in request.Headers) + { + if (!usesStreamContent && (header.Key.Equals("Content-Type", StringComparison.OrdinalIgnoreCase) || header.Key.Equals("Content-Length", StringComparison.OrdinalIgnoreCase))) + continue; + if (!requestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray())) + requestMessage.Content?.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()); + } + + // Add forwarded headers. + if(shouldAddForwardedHeaders) + AddForwardedHeadersToHttpRequest(context, requestMessage); + + // Set destination and method. + requestMessage.Headers.Host = uri.Authority; + requestMessage.RequestUri = uri; + requestMessage.Method = new HttpMethod(requestMethod); + + return requestMessage; + } + + private static Task SendProxiedHttpRequestAsync(this HttpContext context, HttpRequestMessage message, HttpClient httpClient) + { + return httpClient.SendAsync(message, HttpCompletionOption.ResponseHeadersRead, context.RequestAborted); + } + + private static Task WriteProxiedHttpResponseAsync(this HttpContext context, HttpResponseMessage responseMessage) + { + var response = context.Response; + + response.StatusCode = (int)responseMessage.StatusCode; + foreach (var header in responseMessage.Headers) + { + response.Headers[header.Key] = header.Value.ToArray(); + } + + foreach (var header in responseMessage.Content.Headers) + { + response.Headers[header.Key] = header.Value.ToArray(); + } + + response.Headers.Remove("transfer-encoding"); + + return responseMessage.Content.CopyToAsync(response.Body); + } + + private static void AddForwardedHeadersToHttpRequest(HttpContext context, HttpRequestMessage requestMessage) + { + var request = context.Request; + var connection = context.Connection; + + var host = request.Host.ToString(); + var protocol = request.Scheme; + + var localIp = connection.LocalIpAddress?.ToString(); + var isLocalIpV6 = connection.LocalIpAddress?.AddressFamily == AddressFamily.InterNetworkV6; + + var remoteIp = context.Connection.RemoteIpAddress?.ToString(); + var isRemoteIpV6 = connection.RemoteIpAddress?.AddressFamily == AddressFamily.InterNetworkV6; + + if(remoteIp != null) + requestMessage.Headers.TryAddWithoutValidation("X-Forwarded-For", remoteIp); + requestMessage.Headers.TryAddWithoutValidation("X-Forwarded-Proto", protocol); + requestMessage.Headers.TryAddWithoutValidation("X-Forwarded-Host", host); + + // Fix IPv6 IPs for the `Forwarded` header. + var forwardedHeader = new StringBuilder($"proto={protocol};host={host};"); + + if(localIp != null) + { + if(isLocalIpV6) + localIp = $"\"[{localIp}]\""; + + forwardedHeader.Append("by=").Append(localIp).Append(';'); + } + + if(remoteIp != null) + { + if(isRemoteIpV6) + remoteIp = $"\"[{remoteIp}]\""; + + forwardedHeader.Append("for=").Append(remoteIp).Append(';'); + } + + requestMessage.Headers.TryAddWithoutValidation("Forwarded", forwardedHeader.ToString()); + } + } +} \ No newline at end of file diff --git a/backend/Backend/ProxyMiddleware/Helpers/Helpers.cs b/backend/Backend/ProxyMiddleware/Helpers/Helpers.cs new file mode 100644 index 00000000..0bff0897 --- /dev/null +++ b/backend/Backend/ProxyMiddleware/Helpers/Helpers.cs @@ -0,0 +1,116 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Threading.Tasks; +using System.Web; +using Microsoft.AspNetCore.Http; + +namespace AspNetCore.Proxy +{ + /// + /// The delegate type for computing an endpoint from a context and set of arguments. + /// This takes the form `(, ) => `. + /// + /// The HTTP context of the current request at runtime. + /// The arguments of the current request at runtime. + /// The endpoint string. + public delegate string EndpointComputerToString(HttpContext context, IDictionary arguments); + + /// + /// The delegate type for computing an endpoint from a context and set of arguments. + /// This takes the form `(, ) => `. + /// + /// The HTTP context of the current request at runtime. + /// The arguments of the current request at runtime. + /// The endpoint string as a . + public delegate ValueTask EndpointComputerToValueTask(HttpContext context, IDictionary arguments); + + /// + /// Interface for a builder. + /// + /// The interface type of the builder. + /// The concrete type that the builder creates upon being built. + public interface IBuilder where TConcrete : class + { + /// + /// Gets a 'new` instance initialized from `this` instance. + /// + /// A `new` instance of initialized from `this` instance. + /// + TInterface New(); + + /// + /// Gets a `new` instance of initialized from `this` settings. + /// + /// A `new` instance of initialized from `this` settings. + TConcrete Build(); + } + + internal static class Helpers + { + internal static readonly string HttpProxyClientName = "AspNetCore.Proxy.HttpProxyClient"; + internal static readonly string[] WebSocketNotForwardedHeaders = new[] { "Connection", "Host", "Upgrade", "Sec-WebSocket-Accept", "Sec-WebSocket-Protocol", "Sec-WebSocket-Key", "Sec-WebSocket-Version", "Sec-WebSocket-Extensions" }; + + internal static string TrimTrailingSlashes(this string s) + { + if(!s.EndsWith("/")) + return s; + + var span = s.AsSpan(); + var count = 0; + + for(int k = span.Length - 1; k >= 0; k--) + { + if(s[k] == '/') + count++; + else + break; + } + + return s.Substring(0, s.Length - count); + } + + internal static HttpContent ToHttpContent(this IFormCollection collection, string contentTypeHeader) + { + // @PreferLinux: + // Form content types resource: https://stackoverflow.com/questions/4526273/what-does-enctype-multipart-form-data-mean/28380690 + // There are three possible form content types: + // - text/plain, which should never be used and this does not handle (a request with that will not have IsFormContentType true anyway) + // - application/x-www-form-urlencoded, which doesn't handle file uploads and escapes any special characters + // - multipart/form-data, which does handle files and doesn't require any escaping, but is quite bulky for short data (due to using some content headers for each value, and a boundary sequence between them) + + // A single form element can have multiple values. When sending them they are handled as separate items with the same name, not a singe item with multiple values. + // For example, a=1&a=2. + + var contentType = MediaTypeHeaderValue.Parse(contentTypeHeader); + + if (contentType.MediaType.Equals("application/x-www-form-urlencoded", StringComparison.OrdinalIgnoreCase)) // specification: https://url.spec.whatwg.org/#concept-urlencoded + return new FormUrlEncodedContent(collection.SelectMany(formItemList => formItemList.Value.Select(value => new KeyValuePair(formItemList.Key, value)))); + + if (!contentType.MediaType.Equals("multipart/form-data", StringComparison.OrdinalIgnoreCase)) + throw new Exception($"Unknown form content type `{contentType.MediaType}`."); + + // multipart/form-data specification https://tools.ietf.org/html/rfc7578 + // It has each value separated by a boundary sequence, which is specified in the Content-Type header. + // As a proxy it is probably best to reuse the boundary used in the original request as it is not necessarily random. + var delimiter = contentType.Parameters.Single(p => p.Name.Equals("boundary", StringComparison.OrdinalIgnoreCase)).Value.Trim('"'); + + var multipart = new MultipartFormDataContent(delimiter); + foreach (var formVal in collection) + { + foreach (var value in formVal.Value) + multipart.Add(new StringContent(value), formVal.Key); + } + foreach (var file in collection.Files) + { + var content = new StreamContent(file.OpenReadStream()); + foreach (var header in file.Headers) + content.Headers.TryAddWithoutValidation(header.Key, (IEnumerable)header.Value); + multipart.Add(content, file.Name, file.FileName); + } + return multipart; + } + } +} \ No newline at end of file diff --git a/backend/Backend/ProxyMiddleware/Options/HttpProxyOptions.cs b/backend/Backend/ProxyMiddleware/Options/HttpProxyOptions.cs new file mode 100644 index 00000000..d40f8bc0 --- /dev/null +++ b/backend/Backend/ProxyMiddleware/Options/HttpProxyOptions.cs @@ -0,0 +1,254 @@ +using System; +using System.Net.Http; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; + +namespace AspNetCore.Proxy.Options +{ + /// + /// Defines the builder options that can be set for proxied HTTP operations. + /// + public interface IHttpProxyOptionsBuilder : IBuilder + { + /// + /// Instructs the proxy operation to add `Forwarded` and `X-Forwarded-*` headers. + /// Default behavior is `true`. + /// + /// + /// This instance. + IHttpProxyOptionsBuilder WithShouldAddForwardedHeaders(bool shouldAddForwardedHeaders); + + /// + /// Overrides the default used for making the proxy call. + /// Default is `null`. + /// + /// + /// This instance. + IHttpProxyOptionsBuilder WithHttpClientName(string httpClientName); + + /// + /// A that is invoked upon a call. + /// The result should be `true` if the call is intercepted and **not** meant to be forwarded. + /// + /// + /// This instance. + IHttpProxyOptionsBuilder WithIntercept(Func> intercept); + + /// + /// An that is invoked before the call to the remote endpoint. + /// The can be edited before the call. + /// + /// + /// This instance. + IHttpProxyOptionsBuilder WithBeforeSend(Func beforeSend); + + /// + /// An that is invoked before the response is written to the client. + /// The can be edited before the response is written to the client. + /// + /// + /// This instance. + IHttpProxyOptionsBuilder WithAfterReceive(Func afterReceive); + + /// + /// A that is invoked once if the proxy operation fails. + /// + /// + /// This instance. + IHttpProxyOptionsBuilder WithHandleFailure(Func handleFailure); + } + + /// + /// Defines the builder options that can be set for proxied HTTP operations. + /// + public sealed class HttpProxyOptionsBuilder : IHttpProxyOptionsBuilder + { + private bool _shouldAddForwardedHeaders = true; + private string _httpClientName; + private Func> _intercept; + private Func _beforeSend; + private Func _afterReceive; + private Func _handleFailure; + + /// + /// The default constructor. + /// + private HttpProxyOptionsBuilder() + { + } + + /// + /// Gets a `new`, empty instance of this type. + /// + /// A `new` instance of . + public static HttpProxyOptionsBuilder Instance => new HttpProxyOptionsBuilder(); + + /// + public IHttpProxyOptionsBuilder New() + { + return Instance + .WithShouldAddForwardedHeaders(_shouldAddForwardedHeaders) + .WithHttpClientName(_httpClientName) + .WithIntercept(_intercept) + .WithBeforeSend(_beforeSend) + .WithAfterReceive(_afterReceive) + .WithHandleFailure(_handleFailure); + } + + /// + public HttpProxyOptions Build() + { + return new HttpProxyOptions( + _shouldAddForwardedHeaders, + _httpClientName, + _handleFailure, + _intercept, + _beforeSend, + _afterReceive); + } + + /// + /// Sets the option that instructs the proxy operation to add `Forwarded` and `X-Forwarded-*` headers. + /// Default behavior is `true`. + /// + /// + /// The current instance with the specified option set. + public IHttpProxyOptionsBuilder WithShouldAddForwardedHeaders(bool shouldAddForwardedHeaders) + { + _shouldAddForwardedHeaders = shouldAddForwardedHeaders; + return this; + } + + /// + /// Sets the option that overrides the default used for making the proxy call. + /// Default is `null`. + /// + /// + /// The current instance with the specified option set. + public IHttpProxyOptionsBuilder WithHttpClientName(string httpClientName) + { + _httpClientName = httpClientName; + return this; + } + + /// + /// Sets the that is invoked upon a call. + /// The result should be `true` if the call is intercepted and **not** meant to be forwarded. + /// + /// + /// The current instance with the specified option set. + public IHttpProxyOptionsBuilder WithIntercept(Func> intercept) + { + _intercept = intercept; + return this; + } + + /// + /// Sets the that is invoked before the call to the remote endpoint. + /// The can be edited before the call. + /// + /// + /// The current instance with the specified option set. + public IHttpProxyOptionsBuilder WithBeforeSend(Func beforeSend) + { + _beforeSend = beforeSend; + return this; + } + + /// + /// Sets the that is invoked before the response is written to the client. + /// The can be edited before the response is written to the client. + /// + /// + /// The current instance with the specified option set. + public IHttpProxyOptionsBuilder WithAfterReceive(Func afterReceive) + { + _afterReceive = afterReceive; + return this; + } + + /// + /// Sets the that is invoked once if the proxy operation fails. + /// + /// + /// The current instance with the specified option set. + public IHttpProxyOptionsBuilder WithHandleFailure(Func handleFailure) + { + _handleFailure = handleFailure; + return this; + } + } + + /// + /// Defines the options that can be set for proxied HTTP operations. + /// + public sealed class HttpProxyOptions + { + /// + /// ShouldAddForwardedHeaders property. + /// + /// + /// Instructs the proxy operation to add `Forwarded` and `X-Forwarded-*` headers. + /// Default behavior is `true`. + /// + public bool ShouldAddForwardedHeaders { get; } = true; + + /// + /// HttpClientName property. + /// + /// + /// Overrides the default used for making the proxy call. + /// Default is `null`. + /// + public string HttpClientName { get; } + + /// + /// Intercept property. + /// + /// + /// A that is invoked upon a call. + /// The result should be `true` if the call is intercepted and **not** meant to be forwarded. + /// + public Func> Intercept { get; } + + /// + /// BeforeSend property. + /// + /// + /// An that is invoked before the call to the remote endpoint. + /// The can be edited before the call. + /// + public Func BeforeSend { get; } + + /// + /// AfterReceive property. + /// + /// + /// An that is invoked before the response is written to the client. + /// The can be edited before the response is written to the client. + /// + public Func AfterReceive { get; } + + /// + /// HandleFailure property. + /// + /// A that is invoked once if the proxy operation fails. + public Func HandleFailure { get; } + + internal HttpProxyOptions( + bool shouldAddForwardedHeaders, + string httpClientName, + Func handleFailure, + Func> intercept, + Func beforeSend, + Func afterReceive) + { + ShouldAddForwardedHeaders = shouldAddForwardedHeaders; + HttpClientName = httpClientName; + HandleFailure = handleFailure; + Intercept = intercept; + BeforeSend = beforeSend; + AfterReceive = afterReceive; + } + } +} \ No newline at end of file diff --git a/backend/Backend/ProxyMiddleware/ProxyServerMiddleware.cs b/backend/Backend/ProxyMiddleware/ProxyServerMiddleware.cs deleted file mode 100644 index 0c4a0e55..00000000 --- a/backend/Backend/ProxyMiddleware/ProxyServerMiddleware.cs +++ /dev/null @@ -1,60 +0,0 @@ -using Microsoft.AspNetCore.Http; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net.Http; -using System.Threading.Tasks; - -namespace Backend.ProxyMiddleware -{ - public class ProxyServerMiddleware - { - private readonly RequestDelegate _next; - - public ProxyServerMiddleware(RequestDelegate next) - { - _next = next; - } - - public async Task Invoke(HttpContext context) - { - var endRequest = false; - if (context.Request.Path.Value.Equals("/proxy", StringComparison.OrdinalIgnoreCase)) - { - const string key = "url"; - if (context.Request.Query.ContainsKey(key)) - { - var url = context.Request.Query[key][0]; - await ProjectReqAsync(context, url); - endRequest = true; - } - } - if (!endRequest) - { - await _next(context); - } - } - - private static async Task ProjectReqAsync(HttpContext context, string url) - { - var httpClientHandler = new HttpClientHandler { - AllowAutoRedirect = false - }; - var webRequest = new HttpClient(httpClientHandler); - var localResponse = context.Response; - try - { - using (var remoteStream = await webRequest.GetAsync(url)) - { - localResponse.Clear(); - localResponse.ContentType = "api/Projects"; - localResponse.Headers.Add(); - } - catch (Exception e) - { - // Do some logging here - } - } - } -} diff --git a/backend/Backend/Startup.cs b/backend/Backend/Startup.cs index 3d7e98e8..029dd41e 100644 --- a/backend/Backend/Startup.cs +++ b/backend/Backend/Startup.cs @@ -1,4 +1,4 @@ -using Backend.ProxyMiddleware; +using AspNetCore.Proxy; using Backend.Security; using Backend.Services; using Microsoft.AspNetCore.Builder; @@ -30,6 +30,7 @@ public void ConfigureServices(IServiceCollection services) { services.AddControllers(); + services.AddProxies(); services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "Backend", Version = "v1" }); }); @@ -52,7 +53,6 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) app.UseDeveloperExceptionPage(); app.UseSwagger(); app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Backend v1")); - app.UseProxyServer(); } app.UseHttpsRedirection(); @@ -66,12 +66,4 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) }); } } - - public static class ProxyServerMiddlewareExtension - { - public static IApplicationBuilder UseProxyServer(this IApplicationBuilder builder) - { - return builder.Use(next => new ProxyServerMiddleware(next).Invoke); - } - } } \ No newline at end of file From 15fa8988840cbdda255146662341e798dd91f586 Mon Sep 17 00:00:00 2001 From: SaiVarunVaranasi Date: Wed, 19 May 2021 23:09:17 +0200 Subject: [PATCH 03/32] Synced with backend dev --- backend/Backend/.editorconfig | 3 - backend/Backend/Backend.csproj | 20 -- .../Backend/Controllers/SimaProController.cs | 63 ++--- .../Backend/Properties/launchSettings.json | 18 +- .../ProxyMiddleware/AspNetCore.Proxy.csproj | 24 -- .../ProxyMiddleware/Builders/HttpProxy.cs | 141 ---------- .../ProxyMiddleware/Endpoints/RoundRobin.cs | 26 -- .../ProxyMiddleware/Extensions/Http.cs | 185 ------------- .../ProxyMiddleware/Helpers/Helpers.cs | 116 -------- .../Options/HttpProxyOptions.cs | 254 ------------------ .../Security/SimaProLoginDelegatingHandler.cs | 6 +- .../Backend/Services/SimaProQueryService.cs | 23 -- backend/Backend/Startup.cs | 31 ++- 13 files changed, 46 insertions(+), 864 deletions(-) delete mode 100644 backend/Backend/Backend.csproj delete mode 100644 backend/Backend/ProxyMiddleware/AspNetCore.Proxy.csproj delete mode 100644 backend/Backend/ProxyMiddleware/Builders/HttpProxy.cs delete mode 100644 backend/Backend/ProxyMiddleware/Endpoints/RoundRobin.cs delete mode 100644 backend/Backend/ProxyMiddleware/Extensions/Http.cs delete mode 100644 backend/Backend/ProxyMiddleware/Helpers/Helpers.cs delete mode 100644 backend/Backend/ProxyMiddleware/Options/HttpProxyOptions.cs delete mode 100644 backend/Backend/Services/SimaProQueryService.cs diff --git a/backend/Backend/.editorconfig b/backend/Backend/.editorconfig index 1965d4f0..47fcc1c6 100644 --- a/backend/Backend/.editorconfig +++ b/backend/Backend/.editorconfig @@ -90,6 +90,3 @@ csharp_preferred_modifier_order = public,private,protected,readonly,async,static dotnet_style_qualification_for_field = false:suggestion #prefer properties not to be prefaced with this. or Me. in Visual Basic dotnet_style_qualification_for_property = false:suggestion - -# CS0436: Type conflicts with imported type -dotnet_diagnostic.CS0436.severity = silent diff --git a/backend/Backend/Backend.csproj b/backend/Backend/Backend.csproj deleted file mode 100644 index 0c062427..00000000 --- a/backend/Backend/Backend.csproj +++ /dev/null @@ -1,20 +0,0 @@ - - - - net5.0 - 87db58ea-202e-4b41-8dc7-1fe430479a63 - - - - - - - - - - - Always - - - - diff --git a/backend/Backend/Controllers/SimaProController.cs b/backend/Backend/Controllers/SimaProController.cs index 0677240a..28e58873 100644 --- a/backend/Backend/Controllers/SimaProController.cs +++ b/backend/Backend/Controllers/SimaProController.cs @@ -5,69 +5,36 @@ using System.Linq; using System.Threading.Tasks; -using Backend.Services; using System.Net.Http; using Microsoft.Extensions.Primitives; -using AspNetCore.Proxy.Options; using AspNetCore.Proxy; +using AspNetCore.Proxy.Options; namespace Backend.Controllers -{ - [Route("api/[controller]")] +{ + [Route("[controller]/api")] [ApiController] public class SimaProController : ControllerBase { - SimaProQueryService _simaProQueryService; - - public SimaProController(SimaProQueryService simaProQueryService) - { - _simaProQueryService = simaProQueryService; - } - - [HttpGet] - public async Task GetTest() - { - var response = await _simaProQueryService.TestAsync(); - this.HttpContext.Response.RegisterForDispose(response); - return new HttpResponseMessageResult(response); - } + //Use the SimaPro client that has been registered at startup. + //using the login from the SimaProLoginDelegatingHandler in Starup.cs + private HttpProxyOptions httpProxyOptions = HttpProxyOptionsBuilder.Instance + .WithHttpClientName("SimaProClient") + .Build(); - //copy paste from stackoverflow to build the new response from the response the backend got from the api - public class HttpResponseMessageResult : IActionResult + public SimaProController() { - private readonly HttpResponseMessage _responseMessage; - - public HttpResponseMessageResult(HttpResponseMessage responseMessage) - { - _responseMessage = responseMessage; // could add throw if null - } - - public async Task ExecuteResultAsync(ActionContext context) - { - context.HttpContext.Response.StatusCode = (int)_responseMessage.StatusCode; - - foreach (var header in _responseMessage.Headers) - { - context.HttpContext.Response.Headers.TryAdd(header.Key, new StringValues(header.Value.ToArray())); - } - - using (var stream = await _responseMessage.Content.ReadAsStreamAsync()) - { - await stream.CopyToAsync(context.HttpContext.Response.Body); - await context.HttpContext.Response.Body.FlushAsync(); - } - } } - + /* Http proxy request controller. + to process all the http requests using one connection. + Takes every request in the route so that we can avoid additional endpoints. + */ [Route("{**rest}")] public Task ProxyCatchAll(string rest) { - // If you don't need the query string, then you can remove this. var queryString = this.Request.QueryString.Value; - return this.HttpProxyAsync($"{rest}{queryString}", HttpProxyOptions); + return this.HttpProxyAsync($"{rest}{queryString}", httpProxyOptions); } - } - - + } } diff --git a/backend/Backend/Properties/launchSettings.json b/backend/Backend/Properties/launchSettings.json index 126e6f23..0397352b 100644 --- a/backend/Backend/Properties/launchSettings.json +++ b/backend/Backend/Properties/launchSettings.json @@ -1,17 +1,17 @@ -{ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", "iisSettings": { "windowsAuthentication": false, "anonymousAuthentication": true, "iisExpress": { "applicationUrl": "http://localhost:16294", - "sslPort": 0 + "sslPort": 44323 } }, - "$schema": "http://json.schemastore.org/launchsettings.json", "profiles": { "IIS Express": { "commandName": "IISExpress", - "launchBrowser": true, + "launchBrowser": false, "launchUrl": "swagger", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" @@ -19,13 +19,13 @@ }, "Backend": { "commandName": "Project", - "launchBrowser": true, + "dotnetRunMessages": "true", + "launchBrowser": false, "launchUrl": "swagger", + "applicationUrl": "https://localhost:5001;http://localhost:5000", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" - }, - "dotnetRunMessages": "true", - "applicationUrl": "https://localhost:5001;http://localhost:5000" + } } } -} \ No newline at end of file +} diff --git a/backend/Backend/ProxyMiddleware/AspNetCore.Proxy.csproj b/backend/Backend/ProxyMiddleware/AspNetCore.Proxy.csproj deleted file mode 100644 index 0236c825..00000000 --- a/backend/Backend/ProxyMiddleware/AspNetCore.Proxy.csproj +++ /dev/null @@ -1,24 +0,0 @@ - - - - AspNetCore.Proxy - AspNetCore.Proxy - 4.2.0 - https://github.com/twitchax/aspnetcore.proxy - - netcoreapp3.1;netstandard2.0;net5.0 - latest - false - true - true - Library - - - - - - - - - - diff --git a/backend/Backend/ProxyMiddleware/Builders/HttpProxy.cs b/backend/Backend/ProxyMiddleware/Builders/HttpProxy.cs deleted file mode 100644 index 18febbf3..00000000 --- a/backend/Backend/ProxyMiddleware/Builders/HttpProxy.cs +++ /dev/null @@ -1,141 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using AspNetCore.Proxy.Options; -using Microsoft.AspNetCore.Http; - -namespace AspNetCore.Proxy.Builders -{ - /// - /// Interface for an HTTP proxy builder. - /// - public interface IHttpProxyBuilder : IBuilder - { - /// - /// Sets the endpoint on `this` instance that the proxy-to-build should use. - /// - /// The endpoint to set. - /// The current instance with the specified endpoint set. - IHttpProxyBuilder WithEndpoint(string endpoint); - - /// - /// Sets the endpoint on `this` instance that the proxy-to-build should use. - /// - /// The endpoint to set. This takes the form `(, ) => `. - /// The current instance with the specified endpoint set. - IHttpProxyBuilder WithEndpoint(EndpointComputerToString endpoint); - - /// - /// Sets the endpoint on `this` instance that the proxy-to-build should use. - /// - /// The endpoint to set. This takes the form `(, ) => ` - /// The current instance with the specified endpoint set. - IHttpProxyBuilder WithEndpoint(EndpointComputerToValueTask endpoint); - - /// - /// Sets the options builder on `this` instance that the proxy-to-build should use. - /// - /// The options builder to set. - /// The current instance with the specified options set. - IHttpProxyBuilder WithOptions(IHttpProxyOptionsBuilder options); - - /// - /// Sets the options builder on `this` instance that the proxy-to-build should use. - /// - /// The options builder action to set. This takes the form `() => void`. - /// The current instance with the specified options set. - IHttpProxyBuilder WithOptions(Action builderAction); - } - - /// - /// Concrete type for an HTTP proxy builder. - /// - public sealed class HttpProxyBuilder : IHttpProxyBuilder - { - private EndpointComputerToValueTask _endpointComputer; - - private IHttpProxyOptionsBuilder _optionsBuilder; - - private HttpProxyBuilder() - { - } - - /// - /// Gets a `new`, empty instance of this type. - /// - /// A `new` instance of . - public static HttpProxyBuilder Instance => new HttpProxyBuilder(); - - /// - public IHttpProxyBuilder New() - { - return Instance - .WithEndpoint(_endpointComputer) - .WithOptions(_optionsBuilder?.New()); - } - - /// - public HttpProxy Build() - { - if(_endpointComputer == null) - throw new Exception("The endpoint must be specified on this HTTP proxy builder."); - - return new HttpProxy( - _endpointComputer, - _optionsBuilder?.Build()); - } - - /// - public IHttpProxyBuilder WithEndpoint(string endpoint) => this.WithEndpoint((context, args) => new ValueTask(endpoint)); - - /// - public IHttpProxyBuilder WithEndpoint(EndpointComputerToString endpointComputer) => this.WithEndpoint((context, args) => new ValueTask(endpointComputer(context, args))); - - /// - public IHttpProxyBuilder WithEndpoint(EndpointComputerToValueTask endpointComputer) - { - _endpointComputer = endpointComputer; - return this; - } - - /// - public IHttpProxyBuilder WithOptions(IHttpProxyOptionsBuilder optionsBuilder) - { - _optionsBuilder = optionsBuilder; - return this; - } - - /// - public IHttpProxyBuilder WithOptions(Action builderAction) - { - _optionsBuilder = HttpProxyOptionsBuilder.Instance; - builderAction?.Invoke(_optionsBuilder); - - return this; - } - } - - /// - /// Concrete type for an HTTP proxy definition. - /// - public sealed class HttpProxy - { - /// - /// EndpointComputer property. - /// - /// The endpoint computer to use when proxying requests. - public EndpointComputerToValueTask EndpointComputer { get; internal set; } - - /// - /// Options property. - /// - /// The options to use when proxying requests. - public HttpProxyOptions Options { get; internal set; } - - internal HttpProxy(EndpointComputerToValueTask endpointComputer, HttpProxyOptions options) - { - EndpointComputer = endpointComputer; - Options = options; - } - } -} \ No newline at end of file diff --git a/backend/Backend/ProxyMiddleware/Endpoints/RoundRobin.cs b/backend/Backend/ProxyMiddleware/Endpoints/RoundRobin.cs deleted file mode 100644 index 60b54b00..00000000 --- a/backend/Backend/ProxyMiddleware/Endpoints/RoundRobin.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace AspNetCore.Proxy.Endpoints -{ - /// - /// Round robin endpoint helpers. - /// - public static class RoundRobin - { - /// - /// A helper method that "round robins" over a set of endpoints. - /// - /// The set of endpoints to "round robin" over. - /// An that "round robins" over the provided endpoints. - public static EndpointComputerToString Of(params string[] endpoints) - { - var position = 0; - - return (context, args) => - { - if(position == endpoints.Length) - position = 0; - - return endpoints[position++]; - }; - } - } -} \ No newline at end of file diff --git a/backend/Backend/ProxyMiddleware/Extensions/Http.cs b/backend/Backend/ProxyMiddleware/Extensions/Http.cs deleted file mode 100644 index f2aa64c1..00000000 --- a/backend/Backend/ProxyMiddleware/Extensions/Http.cs +++ /dev/null @@ -1,185 +0,0 @@ -using System; -using System.Linq; -using System.Net.Http; -using System.Net.Sockets; -using System.Text; -using System.Threading.Tasks; -using AspNetCore.Proxy.Builders; -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.DependencyInjection; - -namespace AspNetCore.Proxy -{ - internal static class HttpExtensions - { -#pragma warning disable CS0436 // Type conflicts with imported type - internal static async Task ExecuteHttpProxyOperationAsync(this HttpContext context, HttpProxy httpProxy) -#pragma warning restore CS0436 // Type conflicts with imported type - { - var uri = await context.GetEndpointFromComputerAsync(httpProxy.EndpointComputer).ConfigureAwait(false); - var options = httpProxy.Options; - - try - { - var httpClient = context.RequestServices - .GetService() - .CreateClient(options?.HttpClientName ?? Helpers.HttpProxyClientName); - - // If `true`, this proxy call has been intercepted. - if(options?.Intercept != null && await options.Intercept(context).ConfigureAwait(false)) - return; - - if(context.WebSockets.IsWebSocketRequest) - throw new InvalidOperationException("A WebSocket request cannot be routed as an HTTP proxy operation."); - - if(!uri.StartsWith("http", StringComparison.OrdinalIgnoreCase)) - { - if(httpClient.BaseAddress != null) - uri = $"{httpClient.BaseAddress}{uri}"; - else - throw new InvalidOperationException("Only forwarded addresses starting with 'http://' or 'https://' are supported for HTTP requests."); - } - - var proxiedRequest = context.CreateProxiedHttpRequest(uri, options?.ShouldAddForwardedHeaders ?? true); - - if(options?.BeforeSend != null) - await options.BeforeSend(context, proxiedRequest).ConfigureAwait(false); - var proxiedResponse = await context - .SendProxiedHttpRequestAsync(proxiedRequest, httpClient) - .ConfigureAwait(false); - - if(options?.AfterReceive != null) - await options.AfterReceive(context, proxiedResponse).ConfigureAwait(false); - await context.WriteProxiedHttpResponseAsync(proxiedResponse).ConfigureAwait(false); - } - catch (Exception e) - { - if(!context.Response.HasStarted) - { - if (options?.HandleFailure == null) - { - // If the failures are not caught, then write a generic response. - context.Response.StatusCode = 502 /* BAD GATEWAY */; - await context.Response.WriteAsync($"Request could not be proxied.\n\n{e.Message}\n\n{e.StackTrace}").ConfigureAwait(false); - return; - } - - await options.HandleFailure(context, e).ConfigureAwait(false); - } - } - } - - private static HttpRequestMessage CreateProxiedHttpRequest(this HttpContext context, string uriString, bool shouldAddForwardedHeaders) - { - var uri = new Uri(uriString); - var request = context.Request; - - var requestMessage = new HttpRequestMessage(); - var requestMethod = request.Method; - var usesStreamContent = true; // When using other content types, they specify the Content-Type header, and may also change the Content-Length. - - // Write to request content, when necessary. - if (!HttpMethods.IsGet(requestMethod) && - !HttpMethods.IsHead(requestMethod) && - !HttpMethods.IsDelete(requestMethod) && - !HttpMethods.IsTrace(requestMethod)) - { - if (request.HasFormContentType) - { - usesStreamContent = false; - requestMessage.Content = request.Form.ToHttpContent(request.ContentType); - } - else - { - requestMessage.Content = new StreamContent(request.Body); - } - } - - // Copy the request headers. - foreach (var header in request.Headers) - { - if (!usesStreamContent && (header.Key.Equals("Content-Type", StringComparison.OrdinalIgnoreCase) || header.Key.Equals("Content-Length", StringComparison.OrdinalIgnoreCase))) - continue; - if (!requestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray())) - requestMessage.Content?.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()); - } - - // Add forwarded headers. - if(shouldAddForwardedHeaders) - AddForwardedHeadersToHttpRequest(context, requestMessage); - - // Set destination and method. - requestMessage.Headers.Host = uri.Authority; - requestMessage.RequestUri = uri; - requestMessage.Method = new HttpMethod(requestMethod); - - return requestMessage; - } - - private static Task SendProxiedHttpRequestAsync(this HttpContext context, HttpRequestMessage message, HttpClient httpClient) - { - return httpClient.SendAsync(message, HttpCompletionOption.ResponseHeadersRead, context.RequestAborted); - } - - private static Task WriteProxiedHttpResponseAsync(this HttpContext context, HttpResponseMessage responseMessage) - { - var response = context.Response; - - response.StatusCode = (int)responseMessage.StatusCode; - foreach (var header in responseMessage.Headers) - { - response.Headers[header.Key] = header.Value.ToArray(); - } - - foreach (var header in responseMessage.Content.Headers) - { - response.Headers[header.Key] = header.Value.ToArray(); - } - - response.Headers.Remove("transfer-encoding"); - - return responseMessage.Content.CopyToAsync(response.Body); - } - - private static void AddForwardedHeadersToHttpRequest(HttpContext context, HttpRequestMessage requestMessage) - { - var request = context.Request; - var connection = context.Connection; - - var host = request.Host.ToString(); - var protocol = request.Scheme; - - var localIp = connection.LocalIpAddress?.ToString(); - var isLocalIpV6 = connection.LocalIpAddress?.AddressFamily == AddressFamily.InterNetworkV6; - - var remoteIp = context.Connection.RemoteIpAddress?.ToString(); - var isRemoteIpV6 = connection.RemoteIpAddress?.AddressFamily == AddressFamily.InterNetworkV6; - - if(remoteIp != null) - requestMessage.Headers.TryAddWithoutValidation("X-Forwarded-For", remoteIp); - requestMessage.Headers.TryAddWithoutValidation("X-Forwarded-Proto", protocol); - requestMessage.Headers.TryAddWithoutValidation("X-Forwarded-Host", host); - - // Fix IPv6 IPs for the `Forwarded` header. - var forwardedHeader = new StringBuilder($"proto={protocol};host={host};"); - - if(localIp != null) - { - if(isLocalIpV6) - localIp = $"\"[{localIp}]\""; - - forwardedHeader.Append("by=").Append(localIp).Append(';'); - } - - if(remoteIp != null) - { - if(isRemoteIpV6) - remoteIp = $"\"[{remoteIp}]\""; - - forwardedHeader.Append("for=").Append(remoteIp).Append(';'); - } - - requestMessage.Headers.TryAddWithoutValidation("Forwarded", forwardedHeader.ToString()); - } - } -} \ No newline at end of file diff --git a/backend/Backend/ProxyMiddleware/Helpers/Helpers.cs b/backend/Backend/ProxyMiddleware/Helpers/Helpers.cs deleted file mode 100644 index 0bff0897..00000000 --- a/backend/Backend/ProxyMiddleware/Helpers/Helpers.cs +++ /dev/null @@ -1,116 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net.Http; -using System.Net.Http.Headers; -using System.Threading.Tasks; -using System.Web; -using Microsoft.AspNetCore.Http; - -namespace AspNetCore.Proxy -{ - /// - /// The delegate type for computing an endpoint from a context and set of arguments. - /// This takes the form `(, ) => `. - /// - /// The HTTP context of the current request at runtime. - /// The arguments of the current request at runtime. - /// The endpoint string. - public delegate string EndpointComputerToString(HttpContext context, IDictionary arguments); - - /// - /// The delegate type for computing an endpoint from a context and set of arguments. - /// This takes the form `(, ) => `. - /// - /// The HTTP context of the current request at runtime. - /// The arguments of the current request at runtime. - /// The endpoint string as a . - public delegate ValueTask EndpointComputerToValueTask(HttpContext context, IDictionary arguments); - - /// - /// Interface for a builder. - /// - /// The interface type of the builder. - /// The concrete type that the builder creates upon being built. - public interface IBuilder where TConcrete : class - { - /// - /// Gets a 'new` instance initialized from `this` instance. - /// - /// A `new` instance of initialized from `this` instance. - /// - TInterface New(); - - /// - /// Gets a `new` instance of initialized from `this` settings. - /// - /// A `new` instance of initialized from `this` settings. - TConcrete Build(); - } - - internal static class Helpers - { - internal static readonly string HttpProxyClientName = "AspNetCore.Proxy.HttpProxyClient"; - internal static readonly string[] WebSocketNotForwardedHeaders = new[] { "Connection", "Host", "Upgrade", "Sec-WebSocket-Accept", "Sec-WebSocket-Protocol", "Sec-WebSocket-Key", "Sec-WebSocket-Version", "Sec-WebSocket-Extensions" }; - - internal static string TrimTrailingSlashes(this string s) - { - if(!s.EndsWith("/")) - return s; - - var span = s.AsSpan(); - var count = 0; - - for(int k = span.Length - 1; k >= 0; k--) - { - if(s[k] == '/') - count++; - else - break; - } - - return s.Substring(0, s.Length - count); - } - - internal static HttpContent ToHttpContent(this IFormCollection collection, string contentTypeHeader) - { - // @PreferLinux: - // Form content types resource: https://stackoverflow.com/questions/4526273/what-does-enctype-multipart-form-data-mean/28380690 - // There are three possible form content types: - // - text/plain, which should never be used and this does not handle (a request with that will not have IsFormContentType true anyway) - // - application/x-www-form-urlencoded, which doesn't handle file uploads and escapes any special characters - // - multipart/form-data, which does handle files and doesn't require any escaping, but is quite bulky for short data (due to using some content headers for each value, and a boundary sequence between them) - - // A single form element can have multiple values. When sending them they are handled as separate items with the same name, not a singe item with multiple values. - // For example, a=1&a=2. - - var contentType = MediaTypeHeaderValue.Parse(contentTypeHeader); - - if (contentType.MediaType.Equals("application/x-www-form-urlencoded", StringComparison.OrdinalIgnoreCase)) // specification: https://url.spec.whatwg.org/#concept-urlencoded - return new FormUrlEncodedContent(collection.SelectMany(formItemList => formItemList.Value.Select(value => new KeyValuePair(formItemList.Key, value)))); - - if (!contentType.MediaType.Equals("multipart/form-data", StringComparison.OrdinalIgnoreCase)) - throw new Exception($"Unknown form content type `{contentType.MediaType}`."); - - // multipart/form-data specification https://tools.ietf.org/html/rfc7578 - // It has each value separated by a boundary sequence, which is specified in the Content-Type header. - // As a proxy it is probably best to reuse the boundary used in the original request as it is not necessarily random. - var delimiter = contentType.Parameters.Single(p => p.Name.Equals("boundary", StringComparison.OrdinalIgnoreCase)).Value.Trim('"'); - - var multipart = new MultipartFormDataContent(delimiter); - foreach (var formVal in collection) - { - foreach (var value in formVal.Value) - multipart.Add(new StringContent(value), formVal.Key); - } - foreach (var file in collection.Files) - { - var content = new StreamContent(file.OpenReadStream()); - foreach (var header in file.Headers) - content.Headers.TryAddWithoutValidation(header.Key, (IEnumerable)header.Value); - multipart.Add(content, file.Name, file.FileName); - } - return multipart; - } - } -} \ No newline at end of file diff --git a/backend/Backend/ProxyMiddleware/Options/HttpProxyOptions.cs b/backend/Backend/ProxyMiddleware/Options/HttpProxyOptions.cs deleted file mode 100644 index d40f8bc0..00000000 --- a/backend/Backend/ProxyMiddleware/Options/HttpProxyOptions.cs +++ /dev/null @@ -1,254 +0,0 @@ -using System; -using System.Net.Http; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; - -namespace AspNetCore.Proxy.Options -{ - /// - /// Defines the builder options that can be set for proxied HTTP operations. - /// - public interface IHttpProxyOptionsBuilder : IBuilder - { - /// - /// Instructs the proxy operation to add `Forwarded` and `X-Forwarded-*` headers. - /// Default behavior is `true`. - /// - /// - /// This instance. - IHttpProxyOptionsBuilder WithShouldAddForwardedHeaders(bool shouldAddForwardedHeaders); - - /// - /// Overrides the default used for making the proxy call. - /// Default is `null`. - /// - /// - /// This instance. - IHttpProxyOptionsBuilder WithHttpClientName(string httpClientName); - - /// - /// A that is invoked upon a call. - /// The result should be `true` if the call is intercepted and **not** meant to be forwarded. - /// - /// - /// This instance. - IHttpProxyOptionsBuilder WithIntercept(Func> intercept); - - /// - /// An that is invoked before the call to the remote endpoint. - /// The can be edited before the call. - /// - /// - /// This instance. - IHttpProxyOptionsBuilder WithBeforeSend(Func beforeSend); - - /// - /// An that is invoked before the response is written to the client. - /// The can be edited before the response is written to the client. - /// - /// - /// This instance. - IHttpProxyOptionsBuilder WithAfterReceive(Func afterReceive); - - /// - /// A that is invoked once if the proxy operation fails. - /// - /// - /// This instance. - IHttpProxyOptionsBuilder WithHandleFailure(Func handleFailure); - } - - /// - /// Defines the builder options that can be set for proxied HTTP operations. - /// - public sealed class HttpProxyOptionsBuilder : IHttpProxyOptionsBuilder - { - private bool _shouldAddForwardedHeaders = true; - private string _httpClientName; - private Func> _intercept; - private Func _beforeSend; - private Func _afterReceive; - private Func _handleFailure; - - /// - /// The default constructor. - /// - private HttpProxyOptionsBuilder() - { - } - - /// - /// Gets a `new`, empty instance of this type. - /// - /// A `new` instance of . - public static HttpProxyOptionsBuilder Instance => new HttpProxyOptionsBuilder(); - - /// - public IHttpProxyOptionsBuilder New() - { - return Instance - .WithShouldAddForwardedHeaders(_shouldAddForwardedHeaders) - .WithHttpClientName(_httpClientName) - .WithIntercept(_intercept) - .WithBeforeSend(_beforeSend) - .WithAfterReceive(_afterReceive) - .WithHandleFailure(_handleFailure); - } - - /// - public HttpProxyOptions Build() - { - return new HttpProxyOptions( - _shouldAddForwardedHeaders, - _httpClientName, - _handleFailure, - _intercept, - _beforeSend, - _afterReceive); - } - - /// - /// Sets the option that instructs the proxy operation to add `Forwarded` and `X-Forwarded-*` headers. - /// Default behavior is `true`. - /// - /// - /// The current instance with the specified option set. - public IHttpProxyOptionsBuilder WithShouldAddForwardedHeaders(bool shouldAddForwardedHeaders) - { - _shouldAddForwardedHeaders = shouldAddForwardedHeaders; - return this; - } - - /// - /// Sets the option that overrides the default used for making the proxy call. - /// Default is `null`. - /// - /// - /// The current instance with the specified option set. - public IHttpProxyOptionsBuilder WithHttpClientName(string httpClientName) - { - _httpClientName = httpClientName; - return this; - } - - /// - /// Sets the that is invoked upon a call. - /// The result should be `true` if the call is intercepted and **not** meant to be forwarded. - /// - /// - /// The current instance with the specified option set. - public IHttpProxyOptionsBuilder WithIntercept(Func> intercept) - { - _intercept = intercept; - return this; - } - - /// - /// Sets the that is invoked before the call to the remote endpoint. - /// The can be edited before the call. - /// - /// - /// The current instance with the specified option set. - public IHttpProxyOptionsBuilder WithBeforeSend(Func beforeSend) - { - _beforeSend = beforeSend; - return this; - } - - /// - /// Sets the that is invoked before the response is written to the client. - /// The can be edited before the response is written to the client. - /// - /// - /// The current instance with the specified option set. - public IHttpProxyOptionsBuilder WithAfterReceive(Func afterReceive) - { - _afterReceive = afterReceive; - return this; - } - - /// - /// Sets the that is invoked once if the proxy operation fails. - /// - /// - /// The current instance with the specified option set. - public IHttpProxyOptionsBuilder WithHandleFailure(Func handleFailure) - { - _handleFailure = handleFailure; - return this; - } - } - - /// - /// Defines the options that can be set for proxied HTTP operations. - /// - public sealed class HttpProxyOptions - { - /// - /// ShouldAddForwardedHeaders property. - /// - /// - /// Instructs the proxy operation to add `Forwarded` and `X-Forwarded-*` headers. - /// Default behavior is `true`. - /// - public bool ShouldAddForwardedHeaders { get; } = true; - - /// - /// HttpClientName property. - /// - /// - /// Overrides the default used for making the proxy call. - /// Default is `null`. - /// - public string HttpClientName { get; } - - /// - /// Intercept property. - /// - /// - /// A that is invoked upon a call. - /// The result should be `true` if the call is intercepted and **not** meant to be forwarded. - /// - public Func> Intercept { get; } - - /// - /// BeforeSend property. - /// - /// - /// An that is invoked before the call to the remote endpoint. - /// The can be edited before the call. - /// - public Func BeforeSend { get; } - - /// - /// AfterReceive property. - /// - /// - /// An that is invoked before the response is written to the client. - /// The can be edited before the response is written to the client. - /// - public Func AfterReceive { get; } - - /// - /// HandleFailure property. - /// - /// A that is invoked once if the proxy operation fails. - public Func HandleFailure { get; } - - internal HttpProxyOptions( - bool shouldAddForwardedHeaders, - string httpClientName, - Func handleFailure, - Func> intercept, - Func beforeSend, - Func afterReceive) - { - ShouldAddForwardedHeaders = shouldAddForwardedHeaders; - HttpClientName = httpClientName; - HandleFailure = handleFailure; - Intercept = intercept; - BeforeSend = beforeSend; - AfterReceive = afterReceive; - } - } -} \ No newline at end of file diff --git a/backend/Backend/Security/SimaProLoginDelegatingHandler.cs b/backend/Backend/Security/SimaProLoginDelegatingHandler.cs index 0fad994e..415956d8 100644 --- a/backend/Backend/Security/SimaProLoginDelegatingHandler.cs +++ b/backend/Backend/Security/SimaProLoginDelegatingHandler.cs @@ -19,7 +19,7 @@ public class SimaProLoginDelegatingHandler : DelegatingHandler private readonly string simaProPassword; private string accessToken = ""; - + //Gets the credentials from Environment variables. public SimaProLoginDelegatingHandler(IConfiguration configuration) { baseUrl = Environment.GetEnvironmentVariable("BaseUrl") ?? configuration["BaseUrl"]; @@ -27,9 +27,11 @@ public SimaProLoginDelegatingHandler(IConfiguration configuration) simaProPassword = Environment.GetEnvironmentVariable("Password") ?? configuration["Password"]; } + //This will be called everytime a http request comes through HttpClient. protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { + //Get a new access token if the access token expires/not available. if (accessToken != "") { //use token if we already have one @@ -57,7 +59,7 @@ protected override async Task SendAsync(HttpRequestMessage }), Encoding.UTF8, "application/json") }; var loginResponse = await base.SendAsync(loginRequest, cancellationToken); - + if (loginResponse.IsSuccessStatusCode) { diff --git a/backend/Backend/Services/SimaProQueryService.cs b/backend/Backend/Services/SimaProQueryService.cs deleted file mode 100644 index 5c2aa244..00000000 --- a/backend/Backend/Services/SimaProQueryService.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Newtonsoft.Json; -using System.Net.Http; -using System.Threading.Tasks; - -namespace Backend.Services -{ - - public class SimaProQueryService - { - private readonly HttpClient _httpClient; - public SimaProQueryService(HttpClient httpClient) - { - _httpClient = httpClient; - } - - public async Task TestAsync() - { - return await _httpClient.GetAsync("projects"); - } - } - - -} diff --git a/backend/Backend/Startup.cs b/backend/Backend/Startup.cs index 029dd41e..8f5588ac 100644 --- a/backend/Backend/Startup.cs +++ b/backend/Backend/Startup.cs @@ -1,8 +1,8 @@ using AspNetCore.Proxy; using Backend.Security; -using Backend.Services; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.HttpsPolicy; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; @@ -23,6 +23,7 @@ public Startup(IConfiguration configuration) { Configuration = configuration; } + public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. @@ -30,18 +31,20 @@ public void ConfigureServices(IServiceCollection services) { services.AddControllers(); - services.AddProxies(); - services.AddSwaggerGen(c => { + services.AddSwaggerGen(c => + { c.SwaggerDoc("v1", new OpenApiInfo { Title = "Backend", Version = "v1" }); }); + services.AddProxies(); + //Used to get the authenticate/process the Http requests. services.AddTransient(); - services.AddHttpClient( - client => { - var baseUrl = Environment.GetEnvironmentVariable("BaseUrl") ?? Configuration["BaseUrl"]; - client.BaseAddress = new Uri(baseUrl); - //client.Timeout = TimeSpan.FromSeconds(30); - }) + services.AddHttpClient("SimaProClient", + client => { + var baseUrl = Environment.GetEnvironmentVariable("BaseUrl") ?? Configuration["BaseUrl"]; + client.BaseAddress = new Uri(baseUrl); + //client.Timeout = TimeSpan.FromSeconds(30); + }) .AddHttpMessageHandler(); } @@ -51,8 +54,8 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); - app.UseSwagger(); - app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Backend v1")); + //app.UseSwagger(); + //app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Backend v1")); } app.UseHttpsRedirection(); @@ -61,9 +64,11 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) app.UseAuthorization(); - app.UseEndpoints(endpoints => { + app.UseEndpoints(endpoints => + { endpoints.MapControllers(); }); } + } -} \ No newline at end of file +} From 93cfce5b1d67092aef532714c853f1fdff78d242 Mon Sep 17 00:00:00 2001 From: SaiVarunVaranasi Date: Sun, 23 May 2021 16:05:12 +0200 Subject: [PATCH 04/32] Rebased with Backend dev --- .vs/ProjectSettings.json | 3 +++ .vs/slnx.sqlite | Bin 864256 -> 864256 bytes 2 files changed, 3 insertions(+) create mode 100644 .vs/ProjectSettings.json diff --git a/.vs/ProjectSettings.json b/.vs/ProjectSettings.json new file mode 100644 index 00000000..f8b48885 --- /dev/null +++ b/.vs/ProjectSettings.json @@ -0,0 +1,3 @@ +{ + "CurrentProjectSetting": null +} \ No newline at end of file diff --git a/.vs/slnx.sqlite b/.vs/slnx.sqlite index 76fa01ffb77ed64f8fe41f4374b1cacfcf40d354..24d0568df94d67ba6dbbb08560678e1e80fe3ca6 100644 GIT binary patch delta 28938 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 UP;20m=wzQ;Tm^Sc|Fi4=0>hi6c>n+a From 69a233faa442e137d690dcbf53e7629e201a2447 Mon Sep 17 00:00:00 2001 From: Martin Wagner Date: Sat, 29 May 2021 14:23:42 +0200 Subject: [PATCH 05/32] Figured out async handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Regarding #46 Co-authored-by: Martin Dürsch --- .../productGrid/ProductGridComponent.js | 84 ++++++++++++------- frontend/src/interface/simaProInterface.js | 25 +++--- 2 files changed, 64 insertions(+), 45 deletions(-) diff --git a/frontend/src/components/productGrid/ProductGridComponent.js b/frontend/src/components/productGrid/ProductGridComponent.js index 120cf82b..1e20f37d 100644 --- a/frontend/src/components/productGrid/ProductGridComponent.js +++ b/frontend/src/components/productGrid/ProductGridComponent.js @@ -1,8 +1,8 @@ -import React, { useContext } from 'react'; +import React, { useContext, useState, useEffect } from 'react'; import { Column, Row } from 'simple-flexbox'; import { createUseStyles } from 'react-jss'; import MiniCardComponent from 'components/cards/MiniCardComponent'; -import { getProducts } from 'interface/simaProInterface'; +import { getSimaProducts } from 'interface/simaProInterface'; import ProductDropdown from './ModelDropdownComponent'; import SLUGS from 'resources/slugs'; import { Link } from 'react-router-dom'; @@ -21,6 +21,25 @@ import LabelComponent from './LabelComponent'; function ProductGridComponent() { const [selectedProducts] = useContext(PrivateSectionContext); + const [productList, setProductList] = useState([ + { + productID: 'dummydum-13b0-4e09-9fb4-50398483ecfd', //(project_id?) final_process_id? (final_product_id?) + productName: '"please select a Product"', //final_process_name? -> probably rather the project name later. But unclear! + modelID: 'none', + modelName: '"please select a Product"', + productImage: '' + } + ]); + console.log('Tallo'); + useEffect(() => { + async function getProducts() { + const products = await getSimaProducts(); + setProductList(products); + console.log(products); + } + getProducts(); + }, []); + const NewSelectedProducts = [ { productID: selectedProducts.productID, @@ -30,8 +49,7 @@ function ProductGridComponent() { } ]; - const { products = [] } = getProducts(); - console.log(products); + // const { products = [] } = getProducts(); const classes = useStyles(); return ( @@ -42,33 +60,37 @@ function ProductGridComponent() { vertical='center' breakpoints={{ 320: { flexDirection: 'column' } }} > - {products?.map((product, index) => ( - - { - // Save selection to ContextProvider - NewSelectedProducts[0].productID = product.productID; - NewSelectedProducts[0].productName = product.productName; - }} - to={{ - // Link to the next page - pathname: SLUGS.details - }} - > - - - - - - ))} + {console.log('State:')} + {console.log(productList)} + {productList.map((product, index) => + console.log('H') + + // + // { + // // Save selection to ContextProvider + // NewSelectedProducts[0].productID = product.productID; + // NewSelectedProducts[0].productName = product.productName; + // }} + // to={{ + // // Link to the next page + // pathname: SLUGS.details + // }} + // > + // + // + // + // + // + )} ); } diff --git a/frontend/src/interface/simaProInterface.js b/frontend/src/interface/simaProInterface.js index 9a97cfc5..f2561203 100644 --- a/frontend/src/interface/simaProInterface.js +++ b/frontend/src/interface/simaProInterface.js @@ -71,25 +71,22 @@ export function getModels(productID) { * Reducing the SimaPro projects to products. * */ -async function getSimaProducts() { +export async function getSimaProducts() { const httpreq = new BackendConnect(); const products = await httpreq.getSimaProProjects(); + return products; let formattedProducts = []; //console.log(products); - Promise.all( - products.map((product) => { - const productObject = { - productID: product.Id, - productName: product.Name, - categories: [categories.generation, categories.transmission], - productImage: logo - }; - formattedProducts.push(productObject); - }) - ); + products.map((product) => { + const productObject = { + productID: product.Id, + productName: product.Name, + categories: [categories.generation, categories.transmission], + productImage: logo + }; + formattedProducts.push(productObject); + }); return formattedProducts; - - //return getDummyProducts(); } function getDummyProducts() { From dc267cd09370d64c4cc42179b3a6d735e8885bc5 Mon Sep 17 00:00:00 2001 From: Martin Wagner Date: Sun, 30 May 2021 11:05:32 +0200 Subject: [PATCH 06/32] Displaying SimaPro Product Names in the Product Grid Finally! #46 --- .../productGrid/ModelDropdownComponent.js | 30 +++++++- .../productGrid/ProductGridComponent.js | 75 +++++++++---------- frontend/src/interface/simaProInterface.js | 4 +- 3 files changed, 67 insertions(+), 42 deletions(-) diff --git a/frontend/src/components/productGrid/ModelDropdownComponent.js b/frontend/src/components/productGrid/ModelDropdownComponent.js index 27abd12c..f372c1ff 100644 --- a/frontend/src/components/productGrid/ModelDropdownComponent.js +++ b/frontend/src/components/productGrid/ModelDropdownComponent.js @@ -7,6 +7,8 @@ import theme from 'resources/theme'; /** * This component creates the dropdownboxes for the related products * + * It calls the Backend to get the Models for a specific productID + * * @returns the model properties of the related product depending on the model values from getModels func from interface/simaProInterface * @author Parham Gandomkar, Martin Wagner, Irem Toroslu, Mani Anand */ @@ -20,6 +22,32 @@ const ModelDropdownComponent = (props) => { // set the initial values for the dropdown list derived from getModels const variables = getModels(productID); const [selected, setSelected] = useState('Select a model'); + if (variables === null || variables === undefined) { + return ( + + + + + + ); + } + // else: return ( { }; export default ModelDropdownComponent; - - diff --git a/frontend/src/components/productGrid/ProductGridComponent.js b/frontend/src/components/productGrid/ProductGridComponent.js index 1e20f37d..a75dd576 100644 --- a/frontend/src/components/productGrid/ProductGridComponent.js +++ b/frontend/src/components/productGrid/ProductGridComponent.js @@ -8,6 +8,7 @@ import SLUGS from 'resources/slugs'; import { Link } from 'react-router-dom'; import { PrivateSectionContext } from 'hooks/PrivateSectionContext'; import LabelComponent from './LabelComponent'; +import LoadingComponent from 'components/loading'; /** * The Component creates new cards for the product items using the minicard components form 'components/cards/MiniCardComponent' @@ -21,16 +22,12 @@ import LabelComponent from './LabelComponent'; function ProductGridComponent() { const [selectedProducts] = useContext(PrivateSectionContext); - const [productList, setProductList] = useState([ - { - productID: 'dummydum-13b0-4e09-9fb4-50398483ecfd', //(project_id?) final_process_id? (final_product_id?) - productName: '"please select a Product"', //final_process_name? -> probably rather the project name later. But unclear! - modelID: 'none', - modelName: '"please select a Product"', - productImage: '' - } - ]); + const [productList, setProductList] = useState([]); console.log('Tallo'); + /* + * useEffect declars the async function getProducts to be executed after the initial render and + * hooks it so the Component reloads on change. + */ useEffect(() => { async function getProducts() { const products = await getSimaProducts(); @@ -52,6 +49,10 @@ function ProductGridComponent() { // const { products = [] } = getProducts(); const classes = useStyles(); + if (productList === [] || productList === undefined || productList === null) { + return ; + } + // else: return ( {console.log('State:')} {console.log(productList)} - {productList.map((product, index) => - console.log('H') - - // - // { - // // Save selection to ContextProvider - // NewSelectedProducts[0].productID = product.productID; - // NewSelectedProducts[0].productName = product.productName; - // }} - // to={{ - // // Link to the next page - // pathname: SLUGS.details - // }} - // > - // - // - // - // - // - )} + {productList.map((product, index) => ( + + { + // Save selection to ContextProvider + //NewSelectedProducts[0].productID = product.productID; + //NewSelectedProducts[0].productName = product.productName; + }} + to={{ + // Link to the next page + pathname: SLUGS.details + }} + > + + + + + + ))} ); } diff --git a/frontend/src/interface/simaProInterface.js b/frontend/src/interface/simaProInterface.js index f2561203..15590f56 100644 --- a/frontend/src/interface/simaProInterface.js +++ b/frontend/src/interface/simaProInterface.js @@ -64,6 +64,7 @@ export function getModels(productID) { { modelID: 17, productID: productID, modelName: 'Allround Product 4' } ]; default: + return null; break; } } @@ -74,10 +75,9 @@ export function getModels(productID) { export async function getSimaProducts() { const httpreq = new BackendConnect(); const products = await httpreq.getSimaProProjects(); - return products; let formattedProducts = []; //console.log(products); - products.map((product) => { + await products.map((product) => { const productObject = { productID: product.Id, productName: product.Name, From 82f2dddda0cc599d264d9f6265d2fe58bb473f13 Mon Sep 17 00:00:00 2001 From: SaiVarunVaranasi Date: Sun, 30 May 2021 12:44:33 +0200 Subject: [PATCH 07/32] querry to recieve the models for products --- frontend/src/interface/simaProInterface.js | 28 +++++++++++++++++----- package-lock.json | 3 +++ 2 files changed, 25 insertions(+), 6 deletions(-) create mode 100644 package-lock.json diff --git a/frontend/src/interface/simaProInterface.js b/frontend/src/interface/simaProInterface.js index 15590f56..f390ef29 100644 --- a/frontend/src/interface/simaProInterface.js +++ b/frontend/src/interface/simaProInterface.js @@ -10,6 +10,7 @@ import logo_1 from 'assets/dummyImages/Image_1.PNG'; import logo_2 from 'assets/dummyImages/Logo2.png'; import { categories } from './categories'; import { BackendConnect } from 'interface/BackendConnect'; +import axios from 'axios'; /** * should get all the Products from the backend (soon) //TODO: declare and write. @@ -32,7 +33,22 @@ export function getProducts(scope = 'All') { * @returns */ export function getModels(productID) { - switch (productID) { + + const headers = { + Authorization: 'Bearer', + 'My-Custom-Header': 'foobar' + }; + //let result; + console.log("------"); + console.log(productID); + const result2 = axios.get(`https://localhost:44323/SimaPro/api/projects/${productID}`, { headers }); + console.log(result2); + //.then(function (data) { + //const items = data; + //result = items.data.Result.Data; + //}); + //return result; + /* switch (productID) { case '09f64eeb-13b0-4e09-9fb4-50398483ecfd': return [{ modelID: 1, productID: productID, modelName: 'Electric Motor Type 25b' }]; case 'aufwlc93-kldp-4fer-15s7-51245631fega': @@ -62,11 +78,11 @@ export function getModels(productID) { { modelID: 15, productID: productID, modelName: 'Allround Product 2' }, { modelID: 16, productID: productID, modelName: 'Allround Product 3' }, { modelID: 17, productID: productID, modelName: 'Allround Product 4' } - ]; - default: - return null; - break; - } + ]; */ + //default: + // return null; + // break; + //} } /** * Reducing the SimaPro projects to products. diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..48e341a0 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,3 @@ +{ + "lockfileVersion": 1 +} From 57aae20b69ee9afbc858eb87a97a40cf9635079c Mon Sep 17 00:00:00 2001 From: SaiVarunVaranasi Date: Sun, 30 May 2021 14:47:48 +0200 Subject: [PATCH 08/32] querry to recieve the process details for products --- frontend/src/interface/simaProInterface.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/interface/simaProInterface.js b/frontend/src/interface/simaProInterface.js index f390ef29..ae064d19 100644 --- a/frontend/src/interface/simaProInterface.js +++ b/frontend/src/interface/simaProInterface.js @@ -41,7 +41,7 @@ export function getModels(productID) { //let result; console.log("------"); console.log(productID); - const result2 = axios.get(`https://localhost:44323/SimaPro/api/projects/${productID}`, { headers }); + const result2 = axios.get(`https://localhost:44323/SimaPro/api/processes/referencedata/${productID}`, { headers }); console.log(result2); //.then(function (data) { //const items = data; From 3591e19f5c8a3b09513c8494e973112cd47b21ac Mon Sep 17 00:00:00 2001 From: SaiVarunVaranasi Date: Sun, 30 May 2021 17:43:22 +0200 Subject: [PATCH 09/32] Calculations Post Requests --- .../productGrid/ModelDropdownComponent.js | 16 +++++++-- frontend/src/interface/BackendConnect.js | 32 +++++++++++------ frontend/src/interface/simaProInterface.js | 36 ++++++++++--------- 3 files changed, 55 insertions(+), 29 deletions(-) diff --git a/frontend/src/components/productGrid/ModelDropdownComponent.js b/frontend/src/components/productGrid/ModelDropdownComponent.js index f372c1ff..f4efa84d 100644 --- a/frontend/src/components/productGrid/ModelDropdownComponent.js +++ b/frontend/src/components/productGrid/ModelDropdownComponent.js @@ -1,4 +1,4 @@ -import React, { useContext, useState } from 'react'; +import React, { useContext, useState, useEffect } from 'react'; import { getModels } from 'interface/simaProInterface'; import { PrivateSectionContext } from 'hooks/PrivateSectionContext'; import { Col, Container, Row } from 'react-grid-system'; @@ -21,9 +21,21 @@ const ModelDropdownComponent = (props) => { const [getSelectedProducts, setSelectedProducts] = useContext(PrivateSectionContext); // set the initial values for the dropdown list derived from getModels const variables = getModels(productID); + //const [variableList,setVariableList] = useState([productID]); const [selected, setSelected] = useState('Select a model'); + + /*useEffect(() => { + async function getProductModels() { + const variables = getModels(productID); + setVariableList(variables); + console.log(variables); + } + getProductModels(); + }, [productID]); + */ if (variables === null || variables === undefined) { - return ( + if (variableList === null || variableList === undefined) { + return ( -
GET Request with Set Headers
-
- Total react packages: {totalReactPackages} -
- - ); - }*/ + postCalculationRequest(projectId) { + // POST request using axios with set headers + const calcId; + const headers = { + 'Authorization': 'Bearer', + 'My-Custom-Header': 'foobar' + }; + axios.post(`https://localhost:44323/SimaPro/api/calculation/${projectId}`,{ headers }); + //.then(response => this.setState({ articleId: response.data.id })); + postCalculationResultRequest(calcId); + } + + postCalculationResultRequest(calculationId){ + // POST request using axios with set headers + const headers = { + 'Authorization': 'Bearer', + 'My-Custom-Header': 'foobar' + }; + axios.post(`https://localhost:44323/SimaPro/api/calculation/result/${calculationId}`,{ headers }) + .then(response => this.setState({ articleId: response.data.id })); + } } export { BackendConnect }; diff --git a/frontend/src/interface/simaProInterface.js b/frontend/src/interface/simaProInterface.js index ae064d19..1a3d7d59 100644 --- a/frontend/src/interface/simaProInterface.js +++ b/frontend/src/interface/simaProInterface.js @@ -32,23 +32,27 @@ export function getProducts(scope = 'All') { * @param productID the id of the Project to get the models for * @returns */ -export function getModels(productID) { +//export async function getModels(productID) { +export async function getModels(productID) { - const headers = { + /* const headers = { Authorization: 'Bearer', 'My-Custom-Header': 'foobar' }; - //let result; console.log("------"); console.log(productID); - const result2 = axios.get(`https://localhost:44323/SimaPro/api/processes/referencedata/${productID}`, { headers }); - console.log(result2); - //.then(function (data) { - //const items = data; - //result = items.data.Result.Data; - //}); - //return result; - /* switch (productID) { + let resultProcess; + await axios.get(`https://localhost:44323/SimaPro/api/processes/referencedata/${productID}`, { headers }) + .then(function (data) { + const items = data; + resultProcess = items.data.Result.Data; + console.log(resultProcess); + }); + //return resultProcess; */ + //const httpPostReq = BackendConnect(); + + + switch (productID) { case '09f64eeb-13b0-4e09-9fb4-50398483ecfd': return [{ modelID: 1, productID: productID, modelName: 'Electric Motor Type 25b' }]; case 'aufwlc93-kldp-4fer-15s7-51245631fega': @@ -78,11 +82,11 @@ export function getModels(productID) { { modelID: 15, productID: productID, modelName: 'Allround Product 2' }, { modelID: 16, productID: productID, modelName: 'Allround Product 3' }, { modelID: 17, productID: productID, modelName: 'Allround Product 4' } - ]; */ - //default: - // return null; - // break; - //} + ]; + default: + return null; + break; + } } /** * Reducing the SimaPro projects to products. From 184b000725f3568ead82b29173e6323a08caf034 Mon Sep 17 00:00:00 2001 From: SaiVarunVaranasi Date: Mon, 31 May 2021 10:22:08 +0200 Subject: [PATCH 10/32] Calculations Post Requests and get methods for calculation --- .../productGrid/ModelDropdownComponent.js | 81 ++++++++++++++++++- frontend/src/interface/BackendConnect.js | 68 ++++++++++++++-- frontend/src/interface/simaProInterface.js | 19 ----- 3 files changed, 141 insertions(+), 27 deletions(-) diff --git a/frontend/src/components/productGrid/ModelDropdownComponent.js b/frontend/src/components/productGrid/ModelDropdownComponent.js index f4efa84d..780993dd 100644 --- a/frontend/src/components/productGrid/ModelDropdownComponent.js +++ b/frontend/src/components/productGrid/ModelDropdownComponent.js @@ -1,8 +1,9 @@ -import React, { useContext, useState, useEffect } from 'react'; +import React, { useContext, useState } from 'react'; import { getModels } from 'interface/simaProInterface'; import { PrivateSectionContext } from 'hooks/PrivateSectionContext'; import { Col, Container, Row } from 'react-grid-system'; import theme from 'resources/theme'; +import LoadingComponent from 'components/loading'; /** * This component creates the dropdownboxes for the related products @@ -12,7 +13,82 @@ import theme from 'resources/theme'; * @returns the model properties of the related product depending on the model values from getModels func from interface/simaProInterface * @author Parham Gandomkar, Martin Wagner, Irem Toroslu, Mani Anand */ + const ModelDropdownComponent = (props) => { + const productID = props.productID; + const productName = props.productName; + + // eslint-disable-next-line + const [getSelectedProducts, setSelectedProducts] = useContext(PrivateSectionContext); + // set the initial values for the dropdown list derived from getModels + const variables = getModels(productID); + const [selected, setSelected] = useState('Select a model'); + //checking if the variable list is empty + if (variables === [] || variables === undefined || variables === null) { + return ; + } + + return ( + + + + +
+ {variables.map((item) => ( + + ))} +
+ +
+
+ ); +}; + +export default ModelDropdownComponent; + +/* const ModelDropdownComponent = (props) => { const productID = props.productID; const productName = props.productName; @@ -32,7 +108,7 @@ const ModelDropdownComponent = (props) => { } getProductModels(); }, [productID]); - */ + }; if (variables === null || variables === undefined) { if (variableList === null || variableList === undefined) { return ( @@ -119,3 +195,4 @@ const ModelDropdownComponent = (props) => { }; export default ModelDropdownComponent; +*/ \ No newline at end of file diff --git a/frontend/src/interface/BackendConnect.js b/frontend/src/interface/BackendConnect.js index 2b7d2615..6fca2141 100644 --- a/frontend/src/interface/BackendConnect.js +++ b/frontend/src/interface/BackendConnect.js @@ -1,6 +1,12 @@ import axios from 'axios'; class BackendConnect { + + /** + * Get request to det the details of all the projects from the API via backend. + * @returns the list of all the projects. + * + */ async getSimaProProjects() { // GET request using axios with set headers const headers = { @@ -16,27 +22,77 @@ class BackendConnect { }); return result; } - + /** + * Post request to initiate the calculation for a project based on the project id. + * This request returns the calculationId(calcd). which is then used to retrieve the impact + * results of a project. + */ postCalculationRequest(projectId) { // POST request using axios with set headers - const calcId; + let calcId; const headers = { 'Authorization': 'Bearer', 'My-Custom-Header': 'foobar' }; axios.post(`https://localhost:44323/SimaPro/api/calculation/${projectId}`,{ headers }); //.then(response => this.setState({ articleId: response.data.id })); - postCalculationResultRequest(calcId); + this.postCalculationResultRequest(calcId); + return true; } - + /** + * Post request to retrieve the impact calculations for a project based on the calculationId + * from the previous request. + */ postCalculationResultRequest(calculationId){ // POST request using axios with set headers const headers = { 'Authorization': 'Bearer', 'My-Custom-Header': 'foobar' }; - axios.post(`https://localhost:44323/SimaPro/api/calculation/result/${calculationId}`,{ headers }) - .then(response => this.setState({ articleId: response.data.id })); + axios.post(`https://localhost:44323/SimaPro/api/calculation/result/${calculationId}`,{ headers }); + //.then(response => this.setState({ articleId: response.data.id })); + return true; + } + + /** + * Getrequest to get the processes for a model based on the project Id + * + */ + getProjectProcesses(projectId){ + const headers = { + Authorization: 'Bearer', + 'My-Custom-Header': 'foobar' + }; + //console.log("------"); + //console.log(productID); + let resultProcess; + await axios.get(`https://localhost:44323/SimaPro/api/processes/referencedata/${productID}`, { headers }) + .then(function (data) { + const items = data; + resultProcess = items.data.Result.Data; + console.log(resultProcess); + }); + return resultProcess; + } + + /** + * Get request to get all the methods required for drop down. + * @returns the list of methods + */ + getMethods(){ + const headers = { + Authorization: 'Bearer', + 'My-Custom-Header': 'foobar' + }; + let methods; + await axios + .get('https://localhost:44323/SimaPro/api/methods', { headers }) + //Please verify this step + .then(function (data) { + const items = data; + methods = items.data.Result.Data; + }); + return methods; } } diff --git a/frontend/src/interface/simaProInterface.js b/frontend/src/interface/simaProInterface.js index 1a3d7d59..dc2803dc 100644 --- a/frontend/src/interface/simaProInterface.js +++ b/frontend/src/interface/simaProInterface.js @@ -10,7 +10,6 @@ import logo_1 from 'assets/dummyImages/Image_1.PNG'; import logo_2 from 'assets/dummyImages/Logo2.png'; import { categories } from './categories'; import { BackendConnect } from 'interface/BackendConnect'; -import axios from 'axios'; /** * should get all the Products from the backend (soon) //TODO: declare and write. @@ -34,24 +33,6 @@ export function getProducts(scope = 'All') { */ //export async function getModels(productID) { export async function getModels(productID) { - - /* const headers = { - Authorization: 'Bearer', - 'My-Custom-Header': 'foobar' - }; - console.log("------"); - console.log(productID); - let resultProcess; - await axios.get(`https://localhost:44323/SimaPro/api/processes/referencedata/${productID}`, { headers }) - .then(function (data) { - const items = data; - resultProcess = items.data.Result.Data; - console.log(resultProcess); - }); - //return resultProcess; */ - //const httpPostReq = BackendConnect(); - - switch (productID) { case '09f64eeb-13b0-4e09-9fb4-50398483ecfd': return [{ modelID: 1, productID: productID, modelName: 'Electric Motor Type 25b' }]; From 5a8f0f3160c52567e388e9fa9aa2b554fe885d87 Mon Sep 17 00:00:00 2001 From: Martin Wagner Date: Mon, 31 May 2021 10:31:38 +0200 Subject: [PATCH 11/32] prettier --- frontend/src/interface/BackendConnect.js | 76 +++++++++++++----------- 1 file changed, 40 insertions(+), 36 deletions(-) diff --git a/frontend/src/interface/BackendConnect.js b/frontend/src/interface/BackendConnect.js index 6fca2141..c8abb95c 100644 --- a/frontend/src/interface/BackendConnect.js +++ b/frontend/src/interface/BackendConnect.js @@ -1,11 +1,10 @@ import axios from 'axios'; class BackendConnect { - /** * Get request to det the details of all the projects from the API via backend. - * @returns the list of all the projects. - * + * @returns the list of all the projects. + * */ async getSimaProProjects() { // GET request using axios with set headers @@ -23,63 +22,68 @@ class BackendConnect { return result; } /** - * Post request to initiate the calculation for a project based on the project id. - * This request returns the calculationId(calcd). which is then used to retrieve the impact - * results of a project. - */ + * Post request to initiate the calculation for a project based on the project id. + * This request returns the calculationId(calcd). which is then used to retrieve the impact + * results of a project. + */ postCalculationRequest(projectId) { // POST request using axios with set headers let calcId; - const headers = { - 'Authorization': 'Bearer', + const headers = { + Authorization: 'Bearer', 'My-Custom-Header': 'foobar' }; - axios.post(`https://localhost:44323/SimaPro/api/calculation/${projectId}`,{ headers }); - //.then(response => this.setState({ articleId: response.data.id })); + axios.post(`https://localhost:44323/SimaPro/api/calculation/${projectId}`, { headers }); + //.then(response => this.setState({ articleId: response.data.id })); this.postCalculationResultRequest(calcId); return true; } /** - * Post request to retrieve the impact calculations for a project based on the calculationId - * from the previous request. + * Post request to retrieve the impact calculations for a project based on the calculationId + * from the previous request. */ - postCalculationResultRequest(calculationId){ + postCalculationResultRequest(calculationId) { // POST request using axios with set headers - const headers = { - 'Authorization': 'Bearer', + const headers = { + Authorization: 'Bearer', 'My-Custom-Header': 'foobar' }; - axios.post(`https://localhost:44323/SimaPro/api/calculation/result/${calculationId}`,{ headers }); - //.then(response => this.setState({ articleId: response.data.id })); - return true; + axios.post(`https://localhost:44323/SimaPro/api/calculation/result/${calculationId}`, { + headers + }); + //.then(response => this.setState({ articleId: response.data.id })); + return true; } - + /** - * Getrequest to get the processes for a model based on the project Id - * - */ - getProjectProcesses(projectId){ + * Getrequest to get the processes for a model based on the project Id + * + */ + async getProjectProcesses(projectId) { const headers = { Authorization: 'Bearer', 'My-Custom-Header': 'foobar' }; - //console.log("------"); - //console.log(productID); - let resultProcess; - await axios.get(`https://localhost:44323/SimaPro/api/processes/referencedata/${productID}`, { headers }) - .then(function (data) { - const items = data; - resultProcess = items.data.Result.Data; - console.log(resultProcess); - }); - return resultProcess; + //console.log("------"); + //console.log(productID); + let resultProcess; + await axios + .get(`https://localhost:44323/SimaPro/api/processes/referencedata/${productID}`, { + headers + }) + .then(function (data) { + const items = data; + resultProcess = items.data.Result.Data; + console.log(resultProcess); + }); + return resultProcess; } /** * Get request to get all the methods required for drop down. * @returns the list of methods */ - getMethods(){ + async getMethods() { const headers = { Authorization: 'Bearer', 'My-Custom-Header': 'foobar' @@ -88,7 +92,7 @@ class BackendConnect { await axios .get('https://localhost:44323/SimaPro/api/methods', { headers }) //Please verify this step - .then(function (data) { + .then(function (data) { const items = data; methods = items.data.Result.Data; }); From 0ca85050595cd98a3fa8424ce14b7a1d26f4bfd9 Mon Sep 17 00:00:00 2001 From: Martin Wagner Date: Mon, 31 May 2021 10:50:31 +0200 Subject: [PATCH 12/32] Some more and some less async --- .../productGrid/ModelDropdownComponent.js | 20 +++++++++++++++---- frontend/src/interface/BackendConnect.js | 4 ++-- frontend/src/interface/simaProInterface.js | 8 ++++---- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/frontend/src/components/productGrid/ModelDropdownComponent.js b/frontend/src/components/productGrid/ModelDropdownComponent.js index 780993dd..44987808 100644 --- a/frontend/src/components/productGrid/ModelDropdownComponent.js +++ b/frontend/src/components/productGrid/ModelDropdownComponent.js @@ -1,4 +1,4 @@ -import React, { useContext, useState } from 'react'; +import React, { useContext, useState, useEffect } from 'react'; import { getModels } from 'interface/simaProInterface'; import { PrivateSectionContext } from 'hooks/PrivateSectionContext'; import { Col, Container, Row } from 'react-grid-system'; @@ -13,7 +13,7 @@ import LoadingComponent from 'components/loading'; * @returns the model properties of the related product depending on the model values from getModels func from interface/simaProInterface * @author Parham Gandomkar, Martin Wagner, Irem Toroslu, Mani Anand */ - const ModelDropdownComponent = (props) => { +const ModelDropdownComponent = (props) => { const productID = props.productID; const productName = props.productName; @@ -21,11 +21,24 @@ import LoadingComponent from 'components/loading'; const [getSelectedProducts, setSelectedProducts] = useContext(PrivateSectionContext); // set the initial values for the dropdown list derived from getModels const variables = getModels(productID); + console.log('variables'); + console.log(variables); const [selected, setSelected] = useState('Select a model'); //checking if the variable list is empty + + /* useEffect(() => { + async function getProductModels() { + const variables = getModels(productID); + setVariableList(variables); + console.log(variables); + } + getProductModels(); + }, []); */ + if (variables === [] || variables === undefined || variables === null) { return ; } + // else: return ( @@ -87,7 +100,6 @@ import LoadingComponent from 'components/loading'; export default ModelDropdownComponent; - /* const ModelDropdownComponent = (props) => { const productID = props.productID; @@ -195,4 +207,4 @@ const ModelDropdownComponent = (props) => { }; export default ModelDropdownComponent; -*/ \ No newline at end of file +*/ diff --git a/frontend/src/interface/BackendConnect.js b/frontend/src/interface/BackendConnect.js index c8abb95c..3edebdc1 100644 --- a/frontend/src/interface/BackendConnect.js +++ b/frontend/src/interface/BackendConnect.js @@ -26,7 +26,7 @@ class BackendConnect { * This request returns the calculationId(calcd). which is then used to retrieve the impact * results of a project. */ - postCalculationRequest(projectId) { + async postCalculationRequest(projectId) { // POST request using axios with set headers let calcId; const headers = { @@ -68,7 +68,7 @@ class BackendConnect { //console.log(productID); let resultProcess; await axios - .get(`https://localhost:44323/SimaPro/api/processes/referencedata/${productID}`, { + .get(`https://localhost:44323/SimaPro/api/processes/referencedata/${projectId}`, { headers }) .then(function (data) { diff --git a/frontend/src/interface/simaProInterface.js b/frontend/src/interface/simaProInterface.js index dc2803dc..fa9b50a2 100644 --- a/frontend/src/interface/simaProInterface.js +++ b/frontend/src/interface/simaProInterface.js @@ -32,7 +32,7 @@ export function getProducts(scope = 'All') { * @returns */ //export async function getModels(productID) { -export async function getModels(productID) { +export function getModels(productID) { switch (productID) { case '09f64eeb-13b0-4e09-9fb4-50398483ecfd': return [{ modelID: 1, productID: productID, modelName: 'Electric Motor Type 25b' }]; @@ -63,7 +63,7 @@ export async function getModels(productID) { { modelID: 15, productID: productID, modelName: 'Allround Product 2' }, { modelID: 16, productID: productID, modelName: 'Allround Product 3' }, { modelID: 17, productID: productID, modelName: 'Allround Product 4' } - ]; + ]; default: return null; break; @@ -77,7 +77,7 @@ export async function getSimaProducts() { const httpreq = new BackendConnect(); const products = await httpreq.getSimaProProjects(); let formattedProducts = []; - //console.log(products); + console.log(products); await products.map((product) => { const productObject = { productID: product.Id, @@ -91,7 +91,7 @@ export async function getSimaProducts() { } function getDummyProducts() { - // WTH are we looking for here? do we need to iterate over projects (api_demo_project, ...) or over final processes? + // WTH are we looking for here? do we need to iterate over projects (api_demo_project, ...) or over final processes? --> We need to iterate over projects. :) const products = [ { productID: '09f64eeb-13b0-4e09-9fb4-50398483ecfd', //(project_id?) final_process_id? (final_product_id?) From ad84bcfbbd4224ecdab2bf8ddbeafc422313bb37 Mon Sep 17 00:00:00 2001 From: Martin Wagner Date: Mon, 31 May 2021 11:00:07 +0200 Subject: [PATCH 13/32] Declaring a documentational TODO see #58 We cannot keep the selection of a model and product as is, if we have multiple models. --- .../productGrid/ProductGridComponent.js | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/frontend/src/components/productGrid/ProductGridComponent.js b/frontend/src/components/productGrid/ProductGridComponent.js index a75dd576..e3a8217e 100644 --- a/frontend/src/components/productGrid/ProductGridComponent.js +++ b/frontend/src/components/productGrid/ProductGridComponent.js @@ -21,7 +21,7 @@ import LoadingComponent from 'components/loading'; */ function ProductGridComponent() { - const [selectedProducts] = useContext(PrivateSectionContext); + const [selectedProducts, setSelectedProducts] = useContext(PrivateSectionContext); const [productList, setProductList] = useState([]); console.log('Tallo'); /* @@ -37,16 +37,16 @@ function ProductGridComponent() { getProducts(); }, []); - const NewSelectedProducts = [ + // TODO: We cannot keep the selection like this, if models are implemented. See #58 + const newSelectedProducts = [ { - productID: selectedProducts.productID, - productName: selectedProducts.productName, - modelID: selectedProducts.modelID, - modelName: selectedProducts.modelName + productID: selectedProducts[0].productID, + productName: selectedProducts[0].productName, + modelID: selectedProducts[0].modelID, + modelName: selectedProducts[0].modelName } ]; - // const { products = [] } = getProducts(); const classes = useStyles(); if (productList === [] || productList === undefined || productList === null) { @@ -68,8 +68,12 @@ function ProductGridComponent() { { // Save selection to ContextProvider - //NewSelectedProducts[0].productID = product.productID; - //NewSelectedProducts[0].productName = product.productName; + newSelectedProducts[0].productID = product.productID; + newSelectedProducts[0].productName = product.productName; + newSelectedProducts[0].modelID = product.productID; // for now 1 Product has 1 Model (itself) + newSelectedProducts[0].modelName = product.productName; + + setSelectedProducts(newSelectedProducts); }} to={{ // Link to the next page From e53d4be52647b2b0c42797e95634c6aff7418d09 Mon Sep 17 00:00:00 2001 From: Martin Wagner Date: Mon, 31 May 2021 12:07:13 +0200 Subject: [PATCH 14/32] Formatting --- frontend/src/components/productGrid/ModelDropdownComponent.js | 2 +- frontend/src/components/productGrid/ProductGridComponent.js | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/frontend/src/components/productGrid/ModelDropdownComponent.js b/frontend/src/components/productGrid/ModelDropdownComponent.js index 44987808..fe23e323 100644 --- a/frontend/src/components/productGrid/ModelDropdownComponent.js +++ b/frontend/src/components/productGrid/ModelDropdownComponent.js @@ -18,7 +18,7 @@ const ModelDropdownComponent = (props) => { const productName = props.productName; // eslint-disable-next-line - const [getSelectedProducts, setSelectedProducts] = useContext(PrivateSectionContext); + const [selectedProducts, setSelectedProducts] = useContext(PrivateSectionContext); // set the initial values for the dropdown list derived from getModels const variables = getModels(productID); console.log('variables'); diff --git a/frontend/src/components/productGrid/ProductGridComponent.js b/frontend/src/components/productGrid/ProductGridComponent.js index e3a8217e..e978d5a3 100644 --- a/frontend/src/components/productGrid/ProductGridComponent.js +++ b/frontend/src/components/productGrid/ProductGridComponent.js @@ -72,7 +72,6 @@ function ProductGridComponent() { newSelectedProducts[0].productName = product.productName; newSelectedProducts[0].modelID = product.productID; // for now 1 Product has 1 Model (itself) newSelectedProducts[0].modelName = product.productName; - setSelectedProducts(newSelectedProducts); }} to={{ From bf343d7a270088dc8bc5fcbc773efd065e2af758 Mon Sep 17 00:00:00 2001 From: SaiVarunVaranasi Date: Tue, 1 Jun 2021 11:30:49 +0200 Subject: [PATCH 15/32] backend CI pipeline fix- removed test folder from backend --- .vs/VSWorkspaceState.json | 7 +-- backend/Test/Test.csproj | 33 -------------- backend/Test/UnitTest1.cs | 90 --------------------------------------- 3 files changed, 2 insertions(+), 128 deletions(-) delete mode 100644 backend/Test/Test.csproj delete mode 100644 backend/Test/UnitTest1.cs diff --git a/.vs/VSWorkspaceState.json b/.vs/VSWorkspaceState.json index 408d82e2..c6ed4e98 100644 --- a/.vs/VSWorkspaceState.json +++ b/.vs/VSWorkspaceState.json @@ -1,11 +1,8 @@ { "ExpandedNodes": [ "", - "\\Backend", - "\\Backend\\Backend", - "\\Backend\\Backend\\Controllers", - "\\Backend\\CarbonFootprintVisualization" + "\\backend" ], - "SelectedNode": "\\Backend\\CarbonFootprintVisualization.sln", + "SelectedNode": "\\backend\\CarbonFootprintVisualization.sln", "PreviewInSolutionExplorer": false } \ No newline at end of file diff --git a/backend/Test/Test.csproj b/backend/Test/Test.csproj deleted file mode 100644 index 4c373857..00000000 --- a/backend/Test/Test.csproj +++ /dev/null @@ -1,33 +0,0 @@ - - - - net5.0 - - false - - 76daf160-71ee-4707-8246-5e708b4ee60a - - - - - - - - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - - - - - diff --git a/backend/Test/UnitTest1.cs b/backend/Test/UnitTest1.cs deleted file mode 100644 index 733e378e..00000000 --- a/backend/Test/UnitTest1.cs +++ /dev/null @@ -1,90 +0,0 @@ -using Castle.Core.Configuration; -using IdentityModel.Client; -using IdentityServer4; -//using IdentityServerHost; -using MiNET.Utils; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using System; -using System.Net; -using System.Net.Http; -using System.Net.Http.Headers; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Xunit; - -namespace SecureAPITests -{ - public class TestApiEndpoints - { - private readonly string baseUrl; - private readonly string simaProUser; - private readonly string simaProPassword; - private readonly object client; - private string accessToken = ""; - - public TestApiEndpoints() - { - baseUrl = Environment.GetEnvironmentVariable("BaseUrl"); - simaProUser = Environment.GetEnvironmentVariable("User"); - simaProPassword = Environment.GetEnvironmentVariable("Password"); - - } - /*private async Task GetAccessToken() - { - var loginRequest = new HttpRequestMessage(new HttpMethod("POST"), baseUrl) - { - Content = new StringContent(JsonConvert.SerializeObject( - new - { - email = simaProUser, - password = simaProPassword - }), Encoding.UTF8, "application/json") - }; - var loginResponse = await base.SendAsync(loginRequest, cancellationToken); - - if (loginResponse.IsSuccessStatusCode) - { - - var loginResponseContent = JObject.Parse(await loginResponse.Content.ReadAsStringAsync()); - accessToken = loginResponseContent["Result"]["AccessToken"]["Token"].ToString(); - request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); - - // Login successful -> Send original request - return await base.SendAsync(request, cancellationToken); - } - return new HttpResponseMessage(); - } - return accessT - } - - [Fact] - public async Task GetAccessTokenWithCreds() - { - string token = await GetAccessToken(); - - Assert.False(string.IsNullOrWhiteSpace(token)); - } - - [Fact] - public async Task HitApiEndpoint() - { - string token = await GetAccessToken(); - - var apiClient = new HttpClient(); - apiClient.SetBearerToken(token); - - var apiResponse = await apiClient.GetAsync($"{ApiBaseUrl}/test"); - - Assert.True(apiResponse.IsSuccessStatusCode); - - var stringResponse = await apiResponse.Content.ReadAsStringAsync(); - - dynamic result = JsonConvert.DeserializeAnonymousType(stringResponse, new { message = "" }); - Assert.Equal("Hello API", result.message); - } - - }*/ - } -} \ No newline at end of file From 3ebb38012dbd6254934c0b3c536b5eb5d140dc56 Mon Sep 17 00:00:00 2001 From: Sai Varun Varanasi <82500909+SaiVarunVaranasi@users.noreply.github.com> Date: Tue, 1 Jun 2021 11:33:22 +0200 Subject: [PATCH 16/32] Updated dotnet.yml removed the automated testing --- .github/workflows/dotnet.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index bfe6b1aa..4ce38de9 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -23,5 +23,3 @@ jobs: run: nuget restore backend/CarbonFootprintVisualization.sln - name: Build run: dotnet build backend/CarbonFootprintVisualization.sln --no-restore - - name: Test - run: dotnet test --no-build --verbosity normal From 7df5eaf91fb7b9b3af9baf83d122a7f921c2598e Mon Sep 17 00:00:00 2001 From: Sai Varun Varanasi <82500909+SaiVarunVaranasi@users.noreply.github.com> Date: Tue, 1 Jun 2021 11:34:21 +0200 Subject: [PATCH 17/32] updated dotnet.yml --- .github/workflows/dotnet.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 4ce38de9..b823efab 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -2,9 +2,9 @@ name: Backend CI on: push: - branches: [ main, backend-dev, release ] + branches: [ main, backend-dev-#46, release ] pull_request: - branches: [ main, backend-dev, release ] + branches: [ main, backend-dev-#46, release ] jobs: buildAndTest: From b9c805960c6683f7b0fb042e162dd92260383798 Mon Sep 17 00:00:00 2001 From: SaiVarunVaranasi Date: Tue, 1 Jun 2021 11:44:12 +0200 Subject: [PATCH 18/32] backend CI pipeline fix- removed test folder from backend --- backend/CarbonFootprintVisualization.sln | 6 ------ 1 file changed, 6 deletions(-) diff --git a/backend/CarbonFootprintVisualization.sln b/backend/CarbonFootprintVisualization.sln index 19be4e34..71d1b5f7 100644 --- a/backend/CarbonFootprintVisualization.sln +++ b/backend/CarbonFootprintVisualization.sln @@ -5,8 +5,6 @@ VisualStudioVersion = 16.0.31205.134 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Backend", "Backend\Backend.csproj", "{40A6CB29-AC0B-4581-8F8F-EE683CC103C9}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test\Test.csproj", "{99AE127E-0806-47AB-8257-B69CBF34D03B}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -17,10 +15,6 @@ Global {40A6CB29-AC0B-4581-8F8F-EE683CC103C9}.Debug|Any CPU.Build.0 = Debug|Any CPU {40A6CB29-AC0B-4581-8F8F-EE683CC103C9}.Release|Any CPU.ActiveCfg = Release|Any CPU {40A6CB29-AC0B-4581-8F8F-EE683CC103C9}.Release|Any CPU.Build.0 = Release|Any CPU - {99AE127E-0806-47AB-8257-B69CBF34D03B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {99AE127E-0806-47AB-8257-B69CBF34D03B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {99AE127E-0806-47AB-8257-B69CBF34D03B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {99AE127E-0806-47AB-8257-B69CBF34D03B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 07e7c93405a39a5010a7c3c47651a3e39dbb91a5 Mon Sep 17 00:00:00 2001 From: Sai Varun Varanasi <82500909+SaiVarunVaranasi@users.noreply.github.com> Date: Tue, 1 Jun 2021 11:49:43 +0200 Subject: [PATCH 19/32] update dotnet.yml --- .github/workflows/dotnet.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index b823efab..f1d7cd53 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -22,4 +22,4 @@ jobs: - name: Nuget Command run: nuget restore backend/CarbonFootprintVisualization.sln - name: Build - run: dotnet build backend/CarbonFootprintVisualization.sln --no-restore + run: dotnet --no-restore From 5c9ff8f662bb28d447192eae30a5565c9493c470 Mon Sep 17 00:00:00 2001 From: Sai Varun Varanasi <82500909+SaiVarunVaranasi@users.noreply.github.com> Date: Tue, 1 Jun 2021 11:52:57 +0200 Subject: [PATCH 20/32] updated dotnet.yml --- .github/workflows/dotnet.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index f1d7cd53..d311db46 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -8,7 +8,7 @@ on: jobs: buildAndTest: - name: Build and Test Backend + name: Build Backend runs-on: ubuntu-latest steps: @@ -22,4 +22,4 @@ jobs: - name: Nuget Command run: nuget restore backend/CarbonFootprintVisualization.sln - name: Build - run: dotnet --no-restore + run: dotnet build backend/CarbonFootprintVisualization.sln --no-restore From 8162a8cc1a57c8578f89e25e7fd28186d2729595 Mon Sep 17 00:00:00 2001 From: Sai Varun Varanasi <82500909+SaiVarunVaranasi@users.noreply.github.com> Date: Tue, 1 Jun 2021 11:57:05 +0200 Subject: [PATCH 21/32] Removed Backend/Backend --- Backend/Backend/Backend.csproj | 20 -------------------- 1 file changed, 20 deletions(-) delete mode 100644 Backend/Backend/Backend.csproj diff --git a/Backend/Backend/Backend.csproj b/Backend/Backend/Backend.csproj deleted file mode 100644 index 0c062427..00000000 --- a/Backend/Backend/Backend.csproj +++ /dev/null @@ -1,20 +0,0 @@ - - - - net5.0 - 87db58ea-202e-4b41-8dc7-1fe430479a63 - - - - - - - - - - - Always - - - - From 02442646fd5fa04e45fdd212c7ec7143cac07edc Mon Sep 17 00:00:00 2001 From: Sai Varun Varanasi <82500909+SaiVarunVaranasi@users.noreply.github.com> Date: Tue, 1 Jun 2021 12:02:43 +0200 Subject: [PATCH 22/32] created backend.csproj --- backend/Backend/backend.csproj | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 backend/Backend/backend.csproj diff --git a/backend/Backend/backend.csproj b/backend/Backend/backend.csproj new file mode 100644 index 00000000..bd519927 --- /dev/null +++ b/backend/Backend/backend.csproj @@ -0,0 +1,13 @@ + + + Exe + netcoreapp5.0 + false + + + + + + + + From 50e223c6b7275b977c1de87e189fa430189d4311 Mon Sep 17 00:00:00 2001 From: Sai Varun Varanasi <82500909+SaiVarunVaranasi@users.noreply.github.com> Date: Tue, 1 Jun 2021 12:06:11 +0200 Subject: [PATCH 23/32] updated backed.csproj to Backend.csproj --- backend/Backend/{backend.csproj => Backend.csproj} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename backend/Backend/{backend.csproj => Backend.csproj} (100%) diff --git a/backend/Backend/backend.csproj b/backend/Backend/Backend.csproj similarity index 100% rename from backend/Backend/backend.csproj rename to backend/Backend/Backend.csproj From 8cdb211b137a1297febd118233144da565f8b75e Mon Sep 17 00:00:00 2001 From: Sai Varun Varanasi <82500909+SaiVarunVaranasi@users.noreply.github.com> Date: Tue, 1 Jun 2021 12:20:50 +0200 Subject: [PATCH 24/32] parallel backend test implementation --- .github/workflows/dotnet.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index d311db46..91ee70e6 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -13,7 +13,11 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Setup .NET + - name: Setup .NET3 + uses: actions/setup-dotnet@v1 + with: + dotnet-version: 3.0.x + - name: Setup .NET5 uses: actions/setup-dotnet@v1 with: dotnet-version: 5.0.x From 1950e87334a43842b1dd5174238483fae5c68b51 Mon Sep 17 00:00:00 2001 From: Sai Varun Varanasi <82500909+SaiVarunVaranasi@users.noreply.github.com> Date: Tue, 1 Jun 2021 12:24:12 +0200 Subject: [PATCH 25/32] updated Backend.csproj --- backend/Backend.csproj | 10 ++++++++++ backend/backend.csproj | 13 ------------- 2 files changed, 10 insertions(+), 13 deletions(-) create mode 100644 backend/Backend.csproj delete mode 100644 backend/backend.csproj diff --git a/backend/Backend.csproj b/backend/Backend.csproj new file mode 100644 index 00000000..c073d60d --- /dev/null +++ b/backend/Backend.csproj @@ -0,0 +1,10 @@ + + + false + + + + + + + diff --git a/backend/backend.csproj b/backend/backend.csproj deleted file mode 100644 index bd519927..00000000 --- a/backend/backend.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - Exe - netcoreapp5.0 - false - - - - - - - - From 3e5be31b0527a118592090f5b14c605a47e441a7 Mon Sep 17 00:00:00 2001 From: Sai Varun Varanasi <82500909+SaiVarunVaranasi@users.noreply.github.com> Date: Tue, 1 Jun 2021 12:24:36 +0200 Subject: [PATCH 26/32] update --- backend/Backend/Backend.csproj | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/backend/Backend/Backend.csproj b/backend/Backend/Backend.csproj index bd519927..985a6c87 100644 --- a/backend/Backend/Backend.csproj +++ b/backend/Backend/Backend.csproj @@ -1,13 +1,11 @@ - - Exe - netcoreapp5.0 - false - - + + false + - + +> From 19abd496d3109a45ab2887546882fc1a33b19041 Mon Sep 17 00:00:00 2001 From: Sai Varun Varanasi <82500909+SaiVarunVaranasi@users.noreply.github.com> Date: Tue, 1 Jun 2021 12:26:27 +0200 Subject: [PATCH 27/32] update --- backend/Backend/Backend.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/Backend/Backend.csproj b/backend/Backend/Backend.csproj index 985a6c87..ad602ffc 100644 --- a/backend/Backend/Backend.csproj +++ b/backend/Backend/Backend.csproj @@ -4,8 +4,8 @@ - - + + > From 2f31c8997b1cadcee01eddb2586a160074c798af Mon Sep 17 00:00:00 2001 From: SaiVarunVaranasi Date: Tue, 1 Jun 2021 12:49:30 +0200 Subject: [PATCH 28/32] backend CI pipeline fix- removed test folder from backend --- backend/Backend/Backend.csproj | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/backend/Backend/Backend.csproj b/backend/Backend/Backend.csproj index ad602ffc..b412042f 100644 --- a/backend/Backend/Backend.csproj +++ b/backend/Backend/Backend.csproj @@ -1,11 +1,21 @@ - + + - false + net5.0 + 87db58ea-202e-4b41-8dc7-1fe430479a63 - - - - + + + + + + + + + Always + + + -> + From df3ac1424547c428fd2d46f0872a793eb963c5da Mon Sep 17 00:00:00 2001 From: Sai Varun Varanasi <82500909+SaiVarunVaranasi@users.noreply.github.com> Date: Tue, 1 Jun 2021 12:53:10 +0200 Subject: [PATCH 29/32] updated dotnet.yml now the build runs on Windows latest as well --- .github/workflows/dotnet.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 91ee70e6..abc4a8d1 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -9,7 +9,7 @@ on: jobs: buildAndTest: name: Build Backend - runs-on: ubuntu-latest + runs-on: [ubuntu-latest, windows-latest] steps: - uses: actions/checkout@v2 From 018988727749239a404262addedad62be28b3be8 Mon Sep 17 00:00:00 2001 From: Sai Varun Varanasi <82500909+SaiVarunVaranasi@users.noreply.github.com> Date: Tue, 1 Jun 2021 13:11:28 +0200 Subject: [PATCH 30/32] updated dotnet.yml to run on multiple os --- .github/workflows/dotnet.yml | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index abc4a8d1..6cb006fc 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -7,16 +7,14 @@ on: branches: [ main, backend-dev-#46, release ] jobs: - buildAndTest: - name: Build Backend - runs-on: [ubuntu-latest, windows-latest] - + build: + name: Build on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macOS-latest] steps: - uses: actions/checkout@v2 - - name: Setup .NET3 - uses: actions/setup-dotnet@v1 - with: - dotnet-version: 3.0.x - name: Setup .NET5 uses: actions/setup-dotnet@v1 with: From 68f3d440b1e05297a4657b0fd7954dc4d7b0f91b Mon Sep 17 00:00:00 2001 From: Martin Wagner Date: Tue, 1 Jun 2021 21:06:55 +0200 Subject: [PATCH 31/32] changing executive branch to backend-dev Preparing for the merge --- .github/workflows/dotnet.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 6cb006fc..5f001ef8 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -2,7 +2,7 @@ name: Backend CI on: push: - branches: [ main, backend-dev-#46, release ] + branches: [ main, backend-dev, release ] pull_request: branches: [ main, backend-dev-#46, release ] From 3034eb9e3dd804c7cc2672e2b3b213566f1e4763 Mon Sep 17 00:00:00 2001 From: Martin Wagner Date: Tue, 1 Jun 2021 21:07:13 +0200 Subject: [PATCH 32/32] changing executive branch to backend-dev prepering for merge --- .github/workflows/dotnet.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 5f001ef8..d6b8c0e6 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -4,7 +4,7 @@ on: push: branches: [ main, backend-dev, release ] pull_request: - branches: [ main, backend-dev-#46, release ] + branches: [ main, backend-dev, release ] jobs: build: