서버 측 다트

부인 성명



Laska는 활발히 개발 중이며 생산에 사용해서는 안 됩니다. API는 향후 버전에서 크게 변경될 수 있습니다.

소개



Dart의 인기가 Flutter 프레임워크와 커뮤니티의 수용에서 비롯된 것은 비밀이 아닙니다. Flutter도 좋아하지만 서버 측이 그리워요. Dart 언어만 사용하여 풀 스택 개발자가 되는 것이 얼마나 멋질 수 있습니까?

새로운 프로젝트를 시작하고 프론트엔드와 백엔드 부분에 사용할 기술을 선택해야 할 때가 있었습니다. 연구 결과 AqueductShelf에 도달했습니다. 둘 다 적극적으로 개발 및 지원되지 않았으므로 Golang용 Echo 또는 Python용 Bottle과 같은 나만의 작은 마이크로 프레임워크를 만드는 아이디어로 이어졌습니다. . 그리고 결정하기 쉬웠습니다. 시간과 동기가 있었습니다 :)

그리고 시작하기 전에 확실히 떠오르는 몇 가지 질문에 답하고 싶습니다. 왜 프레임워크가 하나 더 필요하고 프레임워크가 해결하는 문제는 무엇입니까? 첫 번째는 쉽습니다. JavaScript 개발자에게 물어보세요! 그러나 좋습니다. 진정한 대답은 경쟁입니다. 프레임워크가 많을수록 서로에게서 더 많이 배우고 결국에는 더 나은 앱을 만들 수 있습니다. 두 번째 답은 마이크로서비스와 소규모 애플리케이션용으로 설계 및 구축되었다는 것입니다. 물론 나중에 제공되는 미들웨어 및 확장 기능으로 확장할 수 있는 방법이 있지만 앞서 말했듯이 Bottle 또는 Echo에 대한 Dart 대안으로 취급합니다. 그리고 내가 지어졌다고 말할 때 나는 지어질 것이라는 의미입니다 :)

건축물



프로젝트의 이름을 따서 명명한 Laska는 마이크로 프레임워크이며 Django와 같은 완전한 기능을 갖춘 앱을 목표로 하지 않습니다. 따라서 아키텍처는 매우 간단합니다. 모든 요청은 동일한 프로세스에 의해 처리되는 반면 성능은 Dart의 비동기 특성을 활용하는 데 기반합니다.

작동 방식을 간단히 살펴보겠습니다.



다이어그램에서 볼 수 있듯이 비동기식 서버 처리는 매력처럼 작동합니다 :)

Isolates와 다중 처리를 실험했지만 결국에는 개발자가 추가 제한 사항을 가지고 작업해야 한다고 결정했습니다. 어떤 종류의 소프트웨어를 사용하고 싶은 방식이 아닌데 왜 누군가 그렇게 해야 합니까? 프로그래밍은 쉽고 재미있어야 하므로 Laska에는 일종의 병렬 처리가 없습니다.

무언가를 만들어 봅시다



'Hello world'라는 프로그래밍 언어와 프레임워크를 표현하는 간단한 방법이 있습니다. 사소하게합시다!

import 'package:laska/laska.dart';

void main() async {
  final laska = Laska();

  laska.GET('/hello/:name',
      (context) async => await context.Text("Hello ${context.param('name')}!"));

  await run(laska);
}


여기서 무슨 일이 일어나고 있는지 이해하기 쉽습니다.
  • Laska 객체 초기화
  • '/hello/:name' 경로에서 GET 요청에 대한 핸들러를 추가합니다. 여기서 name는 컨텍스트 매개변수에 대한 자리 표시자입니다
  • .
  • 경로에 지정된 매개변수가 있는 문자열을 반환하는 처리기를 코딩합니다
  • .
  • 및 서버 실행

  • 이제 비동기 서버가 http://localhost:3789에서 실행됩니다.

    보다 현실적인 예



    분명히 'Hello world'는 누군가 프로덕션에 배포할 일종의 실제 애플리케이션이 아닙니다. 보다 현실적인 방법은 사용자 요청을 stdout에 기록하고 인증이 필요한 경로가 있는 서버를 구축하는 것입니다.

    import 'package:laska/laska.dart';
    
    // Custom middleware that checks user access.
    class Acl implements Middleware {
      final allowedRoles;
    
      Acl(this.allowedRoles);
    
      @override
      Future<Function> execute(Function next, Context context) async {
        return (Context c) {
          // In this case it's simple check:
          // Does the request contains `role` header with `admin` value.
          final role = context.request.headers.value('role');
    
          // If the header's `role` is not in `allowedRoles`, reject the request.
          if (!allowedRoles.contains(role)) {
            context.Text('Role $role is not allowed.');
            return null;
          }
          print('Role $role is allowed.');
    
          // Don't forget to call the handler.
          return next(c);
        };
      }
    }
    
    // Custom middleware that prints request path and given prefix.
    class Logger implements Middleware {
      String prefix;
    
      Logger(this.prefix);
    
      @override
      Future<Function> execute(Function next, Context context) async {
        return (Context c) {
          print('$prefix: Path: ${context.path}');
    
          // Don't forget to call the handler.
          return next(c);
        };
      }
    }
    
    void main() async {
      final laska = Laska();
    
      final acl_middleware = Acl(['admin']);
    
      // Add global middleware
      laska.Use(Logger('global'));
    
      // Create handler with per-route middlewares: logger and acl
      laska.GET('/secret', secretHandler,
          middlewares: {Logger('route'), acl_middleware});
    
      // Add route handler, only global middleware will apply
      laska.GET('/users', getUsers);
    
      // Add route with acl middleware, but only for the POST method.
      laska.POST('/users', getUsers, middlewares: {acl_middleware});
    
      await run(laska);
    }
    
    void secretHandler(Context context) async {
      await context.Text('You have access to secret path!');
    }
    
    void getUsers(Context context) async {
      await context.JSON([
        {'id': 1, 'name': 'Make something useful', 'status': 0},
        {'id': 2, 'name': 'Make new website', 'status': 1},
      ]);
    }
    


    이 코드가 자명하기를 바라지만 댓글로 질문을 할 수 있습니다. :)

    로드맵



    🅿️ - P는 예정입니다.
  • ✅ 자리 표시자를 사용한 동적 라우팅
  • ✅ 미들웨어
  • ✅ JSON 처리
  • ✅ 양식 처리
  • ✅ Null 안전
  • 🅿️ 로깅
  • 🅿️ 정적 파일 제공
  • 🅿️ 템플릿 렌더링?
  • 🅿️ 확장 프로그램
  • 🅿️ 건강 검진
  • ❓ 또 뭐야?



  • 저는 더 많은 서버 측 Dart 프로젝트를 보고 싶고 여러분도 그러기를 바랍니다. 그렇게 생각하신다면 GitHub에서 프로젝트에 별표를 표시하고 Dev.to에서 좋아요를 눌러 주시면 매우 고무적일 것입니다.

    좋은 웹페이지 즐겨찾기