控制器
控制器负责处理传入请求并向客户端返回响应。
控制器的目的是接收应用程序的特定请求。路由机制控制哪个控制器接收哪些请求。通常,每个控制器都有多个路由,并且不同的路由可以执行不同的操作。
装饰器 | 纯平台特定的对象 |
---|---|
@Request(), @Req() | req |
@Response(), @Res()* | res |
@Next() | next |
@Session() | req.session |
@Param(key?: string) | req.params / req.params[key] |
@Body(key?: string) | req.body / req.body[key] |
@Query(key?: string) | req.query / req.query[key] |
@Headers(name?: string) | req.headers / req.headers[name] |
@Ip() | req.ip |
@HostParam() | req.hosts |
ts
import {
Controller,
Get,
Post,
Query,
Body,
Param,
Headers,
HttpCode,
} from '@nestjs/common';
import { UserService } from './user.service';
// import { CreateUserDto } from './dto/create-user.dto';
// import { UpdateUserDto } from './dto/update-user.dto';
/**
* 可以通过以下方式来指定此控制器下所有路由的版本号:
* @Controller({
* path: 'user',
* version: '1',
* })
*
* @export
* @class UserController
*/
@Controller('user')
export class UserController {
constructor(private readonly userService: UserService) {}
@Get()
// get读取信息用query
findAll(@Query() query) {
console.log(query);
return {
code: 200,
message: query.name,
};
}
@Post()
// post读取信息用body
create(@Body() body) {
console.log(body);
return {
code: 200,
message: '名字' + body.name + '年龄' + body.age,
};
}
// get 动态路由测试
@Get(':id')
// @HttpCode(500) 控制状态码
findId(@Param('id') param, @Headers() headers) {
console.log(param, headers.cookie);
return {
code: 200,
};
}
}
Get请求
get动态路由
header
Post请求
生成验证码和session以及验证
后端nest框架
先要安装svg-captcha
,用于生成验证码图片:
shell
pnpm install svg-captcha
然后再main.ts
中去配置一下session:
ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { VersioningType } from '@nestjs/common';
import * as session from 'express-session';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.enableVersioning({
type: VersioningType.URI,
});
app.use(
session({
secret: 'Rarrot',
rolling: true,
name: 'Rarrot.sid',
cookie: { maxAge: 666666 }, //过期时间
}),
);
await app.listen(3000);
}
bootstrap();
而后在session-test.service.ts
中写一个service,配置生成的验证码图片的样式:
ts
import { Injectable, Req } from '@nestjs/common';
import * as svgCaptcha from 'svg-captcha';//引入svg-captcha
@Injectable()
export class SessionTestService {
createCode() {
const Captcha=svgCaptcha.create({
size: 4,
noise: 2,
color: true,
fontSize: 50,
width:100,
height:34,
background: '#e0e8f6',
});
return Captcha;
}
}
再在session-test.controller.ts
中定义get和post接口:
ts
import { Controller, Get, Post, Body, Patch, Param, Delete, Req, Res, Session } from '@nestjs/common';
import { SessionTestService } from './session-test.service';
@Controller('session-test')
export class SessionTestController {
constructor(private readonly sessionTestService: SessionTestService) { }
@Get('code')
createCode(@Req() req: any, @Res() res: any, @Session() session: any) {
// 拿到svg-captcha的返回值,text是验证码的值,data是svg的图片
const capture = this.sessionTestService.createCode();
// 将验证码的值存入session
session.code = capture.text;
// 设置响应头
res.type('image/svg+xml');
// 传入验证码的svg图片
res.send(capture.data);
}
@Post('create')
createUser(@Body() body, @Session() session: any) {
// 判断验证码是否正确
console.log(body,session.code)
if (session.code.toLocaleLowerCase() !== body?.code?.toLocaleLowerCase()) {
return {
code: 400,
message: '验证码错误',
};
} else {
return {
code: 200,
message: '登录成功',
session: session
};
}
}
}
前端vue框架
vue
<template>
<div class="wraps">
<el-form :label-position="labelPosition" label-width="100px" :model="formLabelAlign" style="max-width: 460px">
<el-form-item label="账号">
<el-input v-model="formLabelAlign.name" />
</el-form-item>
<el-form-item label="密码">
<el-input type="password" v-model="formLabelAlign.password" />
</el-form-item>
<el-form-item label="验证码">
<div style="display:flex">
<el-input v-model="formLabelAlign.code" />
<img @click="resetCode" :src="codeUrl" alt="">
</div>
</el-form-item>
<el-form-item>
<el-button @click="submit">登录</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script setup lang='ts'>
import { onMounted, reactive, ref } from 'vue';
// 如果使用的是axios,默认是不打开的,需要使用axios.defaults.withcredentials = true才能携带cookie
// 但是这样会导致跨域,所以需要后端设置允许跨域,也可以使用代理,但是代理需要配置
// 也可以使用jsonp,但是jsonp需要后端设置;
// 也可以使用nginx反向代理,但是需要配置;
// 也可以使用cors,但是需要后端设置;
// 也可以使用fetch 但是fetch需要设置mode: 'cors'。
// 以下代码已经在vite.config.ts设置了跨域,所以直接连接url,后端返回svg图片
const codeUrl = ref<string>('/api/session-test/code')
// 重新获取验证码
const resetCode = () => {
codeUrl.value = '/api/session-test/code?' + Math.random()
}
const labelPosition = ref<string>('right')
const formLabelAlign = reactive({
name: "",
password: "",
code: ""
})
// 接口请求
const submit = () => {
fetch('/api/session-test/create', {
method: "POST",
body: JSON.stringify(formLabelAlign),
// 这里需要设置content-type,否则后端无法解析就收不到数据
headers: {
'content-type': 'application/json'
}
}).then(res => res.json()).then(res => {
console.log(res)
})
}
</script>
<style>
* {
padding: 0;
margin: 0;
}
.wraps {
display: flex;
justify-content: center;
align-items: center;
height: inherit;
}
html,
body,
#app {
height: 100%;
}
</style>
前端本地环境下跨域:
ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
server: {
proxy: {
'/api': {
target: 'http://localhost:3000',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
}
}
}
})