langflow-ai / langflow

Langflow is a low-code app builder for RAG and multi-agent AI applications. It’s Python-based and agnostic to any model, API, or database.
http://www.langflow.org
MIT License
28.47k stars 3.66k forks source link

How can set subpath on my langflow ? #3563

Open songjinu opened 2 weeks ago

songjinu commented 2 weeks ago

How can set subpath on my langflow ?

dosubot[bot] commented 2 weeks ago

To set a subpath for your Langflow instance, you need to modify the FastAPI application setup to include a prefix for the subpath. Here’s how you can do it:

  1. Modify the create_app function: In the src/backend/base/langflow/main.py file, update the create_app function to include a prefix for the subpath.

    def create_app():
       """Create the FastAPI app and include the router."""
       configure()
       socketio_server = socketio.AsyncServer(async_mode="asgi", cors_allowed_origins="*", logger=True)
       lifespan = get_lifespan(socketio_server=socketio_server)
       app = FastAPI(lifespan=lifespan)
       origins = ["*"]
    
       app.add_middleware(
           CORSMiddleware,
           allow_origins=origins,
           allow_credentials=True,
           allow_methods=["*"],
           allow_headers=["*"],
       )
       app.add_middleware(JavaScriptMIMETypeMiddleware)
    
       @app.middleware("http")
       async def flatten_query_string_lists(request: Request, call_next):
           flattened: list[tuple[str, str]] = []
           for key, value in request.query_params.multi_items():
               flattened.extend((key, entry) for entry in value.split(","))
    
           request.scope["query_string"] = urlencode(flattened, doseq=True).encode("utf-8")
    
           return await call_next(request)
    
       @app.get("/health")
       def health():
           return {"status": "ok"}
    
       # Add the subpath prefix here
       app.include_router(router, prefix="/myflow")
    
       app = mount_socketio(app, socketio_server)
    
       return app
  2. Update the static files setup: If you are serving static files, ensure they are also served under the subpath. Update the setup_static_files function accordingly.

    def setup_static_files(app: FastAPI, static_files_dir: Path):
       """
       Setup the static files directory.
       Args:
           app (FastAPI): FastAPI app.
           path (str): Path to the static files directory.
       """
       app.mount(
           "/myflow",
           StaticFiles(directory=static_files_dir, html=True),
           name="static",
       )
    
       @app.exception_handler(404)
       async def custom_404_handler(request, __):
           path = static_files_dir / "index.html"
    
           if not path.exists():
               raise RuntimeError(f"File at path {path} does not exist.")
           return FileResponse(path)
  3. Run the application: After making these changes, run your Langflow application as usual:

    python -m langflow run

Now, you should be able to access Langflow at http://localhost:7860/myflow.

For more detailed information, you can refer to the relevant parts of the Langflow codebase [1][2].

To continue talking to Dosu, mention @dosu.

songjinu commented 2 weeks ago

To set a subpath for your Langflow instance, you need to modify the FastAPI application setup to include a prefix for the subpath. Here’s how you can do it:

  1. Modify the create_app function: In the src/backend/base/langflow/main.py file, update the create_app function to include a prefix for the subpath.

    def create_app():
       """Create the FastAPI app and include the router."""
       configure()
       socketio_server = socketio.AsyncServer(async_mode="asgi", cors_allowed_origins="*", logger=True)
       lifespan = get_lifespan(socketio_server=socketio_server)
       app = FastAPI(lifespan=lifespan)
       origins = ["*"]
    
       app.add_middleware(
           CORSMiddleware,
           allow_origins=origins,
           allow_credentials=True,
           allow_methods=["*"],
           allow_headers=["*"],
       )
       app.add_middleware(JavaScriptMIMETypeMiddleware)
    
       @app.middleware("http")
       async def flatten_query_string_lists(request: Request, call_next):
           flattened: list[tuple[str, str]] = []
           for key, value in request.query_params.multi_items():
               flattened.extend((key, entry) for entry in value.split(","))
    
           request.scope["query_string"] = urlencode(flattened, doseq=True).encode("utf-8")
    
           return await call_next(request)
    
       @app.get("/health")
       def health():
           return {"status": "ok"}
    
       # Add the subpath prefix here
       app.include_router(router, prefix="/myflow")
    
       app = mount_socketio(app, socketio_server)
    
       return app
  2. Update the static files setup: If you are serving static files, ensure they are also served under the subpath. Update the setup_static_files function accordingly.

    def setup_static_files(app: FastAPI, static_files_dir: Path):
       """
       Setup the static files directory.
       Args:
           app (FastAPI): FastAPI app.
           path (str): Path to the static files directory.
       """
       app.mount(
           "/myflow",
           StaticFiles(directory=static_files_dir, html=True),
           name="static",
       )
    
       @app.exception_handler(404)
       async def custom_404_handler(request, __):
           path = static_files_dir / "index.html"
    
           if not path.exists():
               raise RuntimeError(f"File at path {path} does not exist.")
           return FileResponse(path)
  3. Run the application: After making these changes, run your Langflow application as usual:
    python -m langflow run

Now, you should be able to access Langflow at http://localhost:7860/myflow.

For more detailed information, you can refer to the relevant parts of the Langflow codebase [1][2].

To continue talking to Dosu, mention @dosu.

@dosu it's not working. when i access to http://localhost:7860/myflow, redict to http://localhost:7860/all

dosubot[bot] commented 2 weeks ago

The redirection to /all is likely caused by existing redirection rules in the frontend code. Specifically, the following lines in the src/frontend/src/routes.tsx file and the catch-all route in src/frontend/src/components/catchAllRoutes/index.tsx are responsible:

  1. Redirection Rule in routes.tsx:

    <Route index element={<Navigate replace to={"all"} />} />
  2. Catch-All Route in index.tsx:

    import { useEffect } from "react";
    import { useNavigate } from "react-router-dom";
    
    export const CatchAllRoute = () => {
      const navigate = useNavigate();
    
      // Redirect to the root ("/") when the catch-all route is matched
      useEffect(() => {
        navigate("/");
      }, []);
    
      return null;
    };

These rules ensure that any unmatched routes will redirect to the root path /, which then redirects to /all [1][2][3].

To fix this, you need to adjust these redirection rules to account for your subpath. Here’s how you can do it:

  1. Update the Redirection Rule in routes.tsx:

    <Route index element={<Navigate replace to={"/myflow/all"} />} />
  2. Update the Catch-All Route in index.tsx:

    import { useEffect } from "react";
    import { useNavigate } from "react-router-dom";
    
    export const CatchAllRoute = () => {
      const navigate = useNavigate();
    
      // Redirect to the subpath ("/myflow") when the catch-all route is matched
      useEffect(() => {
        navigate("/myflow");
      }, []);
    
      return null;
    };

After making these changes, your application should correctly handle the subpath and not redirect to /all.

To continue talking to Dosu, mention @dosu.